• C++复习笔记


      1 // CPPTEST.cpp : 定义控制台应用程序的入口点。
      2 //
      3 
      4 #include "stdafx.h"
      5 
      6 #include<map>
      7 #include<vector>
      8 #include<string>
      9 #include<list>
     10 #include<iostream>
     11 #include <functional>
     12 #include <fstream>
     13 #include <regex>
     14 
     15 using namespace std;
     16 
     17 class CBase{
     18 protected://注意,可以使用C#风格的定义时初始化
     19     std::string name = "NoOne";
     20     int age = -20;
     21     int sex = 1;
     22 public:
     23     float *pData = new float[20]{1, 2, 3, 4, 5};
     24 public:
     25     virtual ~CBase(){//虚析构函数,防止内存泄漏:对基类指针调用delete时,会从子类一直析构到基类
     26         cout << "~cbase" << endl;
     27     }
     28 };
     29 
     30 //基类的私有成员不会被继承,这和C#完全一样
     31 class CStudent : public CBase{
     32 public:
     33     std::map<int, std::string> _projs;
     34     CStudent(){
     35         pData = new float[20]{1, 2, 3, 4, 5};
     36     }
     37 public:
     38     void SetName(const std::string& name){
     39         CBase::name = name;//如果CBase.name定义为私有,这里就不可访问
     40         this->name = name; //等价于上一行
     41     }
     42 
     43     const string& GetName(){
     44         return this->name;
     45     }
     46 
     47     ~CStudent(){//若采用浅拷贝,析构函数被调用多次,pData被删除多次,程序崩溃
     48         //规避方式:判断pData是否为空,非空才delete[] pData
     49         //但在不知情的情况下使用pData仍然会出问题,因此浅拷贝导致的问题不可规避
     50         cout << "~cstudent" << endl;
     51         delete[] pData;
     52         pData = NULL;
     53     }
     54 };
     55 
     56 void TestSTL(){
     57     
     58     auto mp = new std::map<int, std::string>();//c++11新风格 auto
     59     
     60     mp->insert({ 10, ("h你好") });//c++11新风格,不用再使用std::pair()或std::make_pair()
     61     mp->insert({ 20, "el" });
     62     for (auto var : *mp)//c++11新风格for
     63     {
     64         std::cout << var.first << "," << var.second << "," << std::endl;
     65     }
     66 }
     67 
     68 void TestClass(){
     69     CBase* pbase = new CStudent();
     70     auto pst = (CStudent*)pbase;
     71     pst->SetName("xxxx");
     72     auto name = pst->GetName();
     73     delete pbase;
     74 }
     75 
     76 int TestAdd(int a, int b){
     77     return a + b;
     78 }
     79 void TestStdFunc(std::function<int(int,int)> fun, int a, int b){
     80     auto ret = fun(a, b);
     81 }
     82 
     83 typedef int(*TestAddPtr)(int, int);
     84 
     85 void TestPCall(TestAddPtr func, int a, int b){
     86     auto ret = func(a, b);
     87 }
     88 
     89 struct Vertex{
     90     bool isgood;
     91     float x, y, z;
     92     double dx;
     93     bool bx;
     94     int ix;
     95     bool by;
     96 };
     97 void TestFile(){
     98     int szChar = sizeof(char);
     99     ofstream ofs;
    100     ofs.open("f:/test.txt");
    101     ofs << "hello " << 10 << " world " << 20 << endl;
    102 
    103     ofs.flush();
    104     ofs.close();
    105     
    106     ifstream ifs;
    107     ifs.open("f:/test.txt");
    108     string str1, str2;
    109     int num1, num2;
    110 
    111     ifs >> str1 >> num1 >> str2 >> num2;
    112 
    113     //错误示例:二进制读写,使用std::<<或>>进行的还是ASCII码的读写
    114      ofstream ofsb;
    115     ofsb.open("f:/testb", ios::binary);
    116     ofsb << "hellob" << 1022;
    117 
    118     ofsb.flush();
    119     ofsb.close();
    120      ifstream ifsb;
    121 
    122     string sx;
    123     int nx;
    124     ifsb.open("f:/testb", ios::binary);
    125     ifsb >> sx >> nx;
    126     ifsb.close();
    127 
    128     //正确做法
    129     sx = "binary";
    130     nx = 978;
    131     ofsb.open("f:/testbx", ios::binary);
    132     ofsb.write(sx.c_str(), sx.length()*sizeof(char)+1);
    133     ofsb.write((const char*)&(nx), sizeof(int));
    134     ofsb.flush();
    135     ofsb.close();
    136 
    137     char sxr[32];
    138     int nxr;
    139     ifsb.open("f:///testbx", ios::binary);//注意这里的"///"不管有多少个/都等同于一个
    140     ifsb.read(sxr, sx.length()+1);
    141     ifsb.read((char*)&nxr, 4);
    142 
    143     //数据转换的更通用方式
    144     Vertex vt;
    145     vt.bx = true;
    146     vt.isgood = false;
    147     vt.x = 12;
    148     vt.y = 13;
    149     vt.z = 14;
    150     vt.dx = 3.9;
    151     vt.by = 0;
    152 
    153     ofstream ofsbx;
    154     ofsbx.clear();
    155     ofsbx.open("f:/testbyx2", ios::binary);
    156     ofsbx.write((const char*)&(vt), sizeof(Vertex));
    157     ofsbx.flush();
    158     ofsbx.close();
    159 
    160     ifstream ifsbx;
    161     Vertex vrt;
    162     ifsbx.clear();
    163     ifsbx.open("f:/testbyx2", ios::binary);
    164     ifsbx.read((char*)&vrt, sizeof(Vertex));
    165 
    166     string s1 = "hello";
    167     string s2 = "wrold";
    168     s1 = s1 + s2;
    169     auto s3 = s1.substr(1, 2);
    170 }
    171 
    172 //实现较为高效的字符串分割,限制是分割符只能是一个字符,不能是一个串
    173 std::list<string> TestStrSplit(string s, char sep){
    174     std::list<string> lst;
    175     for (int i = 0, j = 0; i < s.length(); ++i){
    176         if (s[i] == sep){
    177             lst.push_back(s.substr(j, i - j));
    178             j = i + 1;
    179         }
    180     }
    181 
    182     //注意临时对象作为返回值了,一般情况下这是错误的用法,栈上的临时对象出了函数域后会被释放
    183     //但这里STL容器内部重载了=运算符,作了值拷贝就没问题了
    184     return lst;
    185 }
    186 void TestString(){
    187 
    188     //g正则表达式实现字符串分割
    189     string s1 = "a;b;c;dddd;ef;";
    190     string s2 = "a123b2673cdd4444a";
    191     std::regex re("(d+)");
    192     std::smatch mtch;
    193 
    194     //这个做法效率挺低且浪费内存,产生了很多中间字符串
    195     while (std::regex_search(s2, mtch, re, std::regex_constants::match_default)){
    196         cout << mtch.str() << endl;
    197         s2 = mtch.suffix();
    198     }
    199 
    200     //这个函数效率要高多了
    201     auto lst = TestStrSplit(s1, ';');
    202     
    203 }
    204 
    205 //返回栈上的临时对象测试
    206 CStudent TestTempObjRet(){
    207     CStudent ost; //临时对象
    208     return ost; //调用对象的拷贝构造函数
    209 }//出了栈后ost被释放,析构函数调用,同时成员对象被析构CStudent.name="",但内置类型仍保持原值
    210 
    211 //通过测试可知,将栈上对象作为函数返回值使用一般是没有问题的,但浅COPY时两个对象中的指针指向同一份
    212 //内存,当一个对象被删除时,另一个对象中的指针就指向非法位置了,成了野指针
    213 void TestObjConstructorAndDestructor(){
    214     CStudent ostx;
    215     ostx = TestTempObjRet(); //调用拷贝构造函数(与上面对应)
    216     auto name = ostx.GetName();
    217     auto px = ostx.pData;
    218 }
    219 
    220 void TestRRef(){
    221 
    222 }
    223 
    224 //可以使用随机访问(数组下标)说明vector在内存中是连续存放的
    225 //这样,vector在需要扩充容量时就需要将原来内存删除,再申请一块新内存
    226 //但这并不一定,因为内存申请时若用realloc则有可能会在原内存后面增加(原理)
    227 void TestVector(){
    228     std::vector<string> sv{ "hello", "world" };
    229     sv[0];
    230     sv[1];
    231     
    232     sv.reserve(20); //旧的内容被清除
    233     int n = sv.capacity(); //20
    234     sv.push_back("a");
    235     sv.push_back("b");
    236     sv.clear(); //旧的内容被清除
    237     n = sv.capacity(); //20
    238 
    239     sv.shrink_to_fit(); //内存释放
    240     n = sv.capacity(); //0
    241 
    242 }
    243 
    244 struct CTA{
    245 private:
    246     virtual void Test(){
    247         cout << "cta" << endl;
    248     }
    249 
    250 };
    251 
    252 class CCTA : CTA{//类和结构体可以相互继承
    253 public:
    254     int _id;
    255     void Test() const{
    256         cout << "ccta-test" << endl;
    257     }
    258 };
    259 
    260 //C++中字符串有常量和变量之分,字符串遇到则结束
    261 //C#中只有常量字符串,字符串遇到不结束,视其为正常字符
    262 void TestStr(){
    263     char* ps = "hello";//字符串常量,不可修改其内容
    264     ps[0] = 'd'; //运行出错
    265 
    266     char arr[] = "hello"; //字符串变量
    267     char* par = arr;
    268     arr[0] = 'd'; //ok
    269 }
    270 
    271 //C++中指针字符串与数组字符串都是自动以0结尾的
    272 void TestMemcpy(){
    273     
    274     char dest[18];
    275     char src[] = "hell"; //以0结尾,长度为5,若强制声明为 char src[4] = "hell"则编译报错
    276     char* psrc = "hell"; //以0结尾,长度为5,但测试长度strlen(psrc)为4,因为它没算尾0
    277     
    278     for (int i = 0; i < 10; ++i){
    279 
    280     }
    281     for (int i = 0, ch; (ch = psrc[i++]) != 0;){
    282         //这里发现字符串尾0后有许多个0,不知道原因
    283 
    284     }
    285     auto len = strlen(psrc); //4,测试长度,并没字符串的真实长度(内存中真实串),因为它有尾0
    286     int len2 = strlen(src); //5,字符串实际长度(内存中存储的字符串)
    287     int st = sizeof(src); //5,数组大小
    288     memcpy(dest, psrc, strlen(psrc)+1);
    289 }
    290 template<typename T1, class T2> class MyVector{
    291     std::vector<int> _lst;
    292 
    293 public:
    294 
    295     void Test2();
    296 };
    297 
    298 template<class T1, class T2> void MyVector<T1, T2>::Test2(){
    299 
    300 }
    301 int _tmain(int argc, _TCHAR* argv[])
    302 {
    303     TestMemcpy();
    304 //     auto pox = new CCTA();
    305 //     pox->Test();
    306 // 
    307 //     MyVector<int, float> _v;
    308     //_v.Test<float>();
    309     //TestSTL();
    310     //TestClass();
    311     //TestStdFunc(TestAdd, 10, 20);
    312     //TestPCall(TestAdd, 10, 23);
    313     //TestFile();
    314     //TestString();
    315     //TestObjConstructorAndDestructor();
    316     //TestVector();
    317 
    318 
    319 
    320     return 0;
    321 }
  • 相关阅读:
    你必须会的 JDK 动态代理和 CGLIB 动态代理
    Dubbo 扩展点加载机制:从 Java SPI 到 Dubbo SPI
    volatile 手摸手带你解析
    Dubbo之服务消费原理
    Dubbo之服务暴露
    ElasticSearch之映射常用操作
    Redis5新特性Streams作消息队列
    .NET 开源项目 StreamJsonRpc 介绍[下篇]
    .NET 开源项目 StreamJsonRpc 介绍[中篇]
    .NET 开源项目 StreamJsonRpc 介绍 [上篇]
  • 原文地址:https://www.cnblogs.com/timeObjserver/p/8717917.html
Copyright © 2020-2023  润新知