zoukankan      html  css  js  c++  java
  • C++ 学习笔记 (一)

    C++标准化组织
      https://isocpp.org/std/status
      http://open-std.org/JTC1/SC22/WG21/

    why C++王者归来?

      https://coolshell.cn/articles/6548.html



    方法论

    学任何知识点,都可以从三个方面来考虑?
    > 是什么? what
    > 怎么实现的? how
    > 为什么? why

    > 学习的深度

    > 讲出来
    > 听得懂


    内存泄漏
    野指针
    内存踩踏


    malloc用法
    malloc底层怎么实现的? ==> 系统调用
    为什么?


    常量和宏的区别

    #include <iostream>
    using std::cout;
    using std::endl;

    //编辑 --> 预处理(预编译) --> 编译 --> 汇编 --> 链接 --> 可执行程序
    //      -E        -S      as   -o
    //
    //概念 ==》沟通
    //
    //怎么表示学会了一个知识点?
    // 完成任务 --> 讲出来 --> 别人还能够听的懂
    //
    //
    //宏定义与const的区别?(概念题是最容易丢分)
    //1. 发生时机不一样: 宏定义发生在预处理时,const关键字发生编译时

    //2. 宏定义仅仅只做了字符串的替换,没有类型检查; const关键字有类型

    检查,可以提前发现错误

    //3. const关键字更推荐使用; 因为使用const关键字可以减小犯错误的概率


    #define NUMBER 1024

    void test0()
    {
      cout << "NUMBER = " << NUMBER << endl;
    }

    void test1()
    {
      const int number = 1;
      cout << ">> number = " << number << endl;

      //const int number2;//error, 必须要进行初始化
    }

    //常量指针 指针常量
    //
    // int(*)[5] int *[5]
    //数组指针 指针数组
    //
    //int(*p)() int* p()
    //函数指针 指针函数


    void test2()
    {
      int number = 10;
      int number2 = 100;
      int * p1 = &number;
      cout << "*p1 = " << *p1 << endl;
      cout << "&p1 = " << &p1 << endl;

      const int * p2 = &number;//常量指针(pointer to const)
      cout << "*p2 = " << *p2 << endl;
      cout << "&p2 = " << &p2 << endl;
      //*p2 = 100;//error 不能通过该指针修改所指变量的值
      p2 = &number2;//可以改变其指向
      cout << "*p2 = " << *p2 << endl;

      int const * p3 = &number;
      //*p3 = 1000;//error
      p3 = &number2;//可以改变其指向

      int * const p4 = &number;//指针常量(const pointer)
      *p4 = 1000;//可以通过该指针改变所指变量的值
      //p4 = &number2;//error 不能改变指向

      //两者都不能修改
      const int * const p5 = &number;
    }


    int main(void)
    {
      //test0();
      //test1();
      test2();

      return 0;
    }


    Hello.cc

    #include <stdio.h> //c标准头文件带有.h后缀
    #include <iostream> //C++标准头文件没有后缀.h
    //是用模板实现的, 必须要知道其实现

    using namespace std;//命名空间

    int main(int argc, char ** argv)
    {
      printf("hello,world! ");//标准库函数
      cout << "hello,world!" << endl;//cout 对象, 输出流运算符
      // operator<<(cout, "hello,world!");
      return 0;
    }


    命名空间namespace

    #include <iostream>
    using namespace std;//using编译指令, 它会一次性把std空间中
    //的所有实体全部引进来
    //
    //要求:熟悉空间中的实体
    //目前来说,不推荐使用

    void wd_display();
    void tls_display();

    void cout()
    {

    }

    namespace wd
    {
      void display()
      {
        cout << "wd::display() " << endl;
      }


    }//end of namespace wd

    namespace tls
    {

      void display()
      {
        cout << "tls::display() " << endl;
      }

    }//end of namespace tls



    int main(void)
    {
      wd::display();//:: 作用域限定符, 这是完整形式
      tls::display();

      return 0;
    }

    namespace2

    #include <iostream>

    using std::cout;// using声明机制, 简化操作, 不会把所有的实体引进来
    using std::endl;

    void wd_display();
    void tls_display();


    struct Example
    {
      int x;
      int y;

    };


    //命名空间在一个文件之中可以出现多次
    //相当于一个黑洞
    namespace wd
    {
      int number = 10;
      void show();//声明
    }//end of namespace wd


    namespace tls
    {

      void display()
      {
        cout << "tls::display() " << endl;
        wd::show();
      }

    }//end of namespace tls

    namespace wd
    {
      void display()
      {
        cout << "wd::display() " << endl;
        tls::display();
      }

      void show()//实现
      {
        cout << "wd::show()" << endl;
        //wd::display();//加上就会发生递归调用:
      }

    }//end of namespace wd


    int main(void)
    {
      wd::display();//:: 作用域限定符
      tls::display();

      cout << "wd::number = " << wd::number << endl;

      return 0;
    }

    namespace3

    //代码风格的限定 ==> code review 代码走查

    //#include "myhead.h" //自定义头文件放在C头文件的上面

    #include <stdio.h> //头文件的顺序: C的头文件放在C++头文件的前面
    #include <stdlib.h>

    #include <iostream>

    using std::cout;//选择区域
    using std::endl;

    int number = 10;

    namespace wd
    {
      int number = 100;


      namespace lwh
      {

        void display()
        {
          cout << "wd::lwh::display()" << endl;
        }
      }//end of namespace lwh

    }//end of namespace wd

    namespace tls
    {
      int number = 1000;

      void display(int number)//形参number会屏蔽其他的number
      {
        cout << "number = " << number << endl;
        cout << "wd::number = " << wd::number << endl;
        cout << "tls::number = " << tls::number << endl;
        cout << "全局变量 number = " << ::number << endl;//匿名命名空间
      }

    }//end of namespace tls


    int test0(void)
    {
      using wd::lwh::display;
      display();
      return 0;
    }

    int main(void)
    {
      //display();
      test0();
      return 0;
    }


    new / delete malloc / free

    #include <stdlib.h>
    #include <string.h>
    #include <iostream>
    using std::cout;
    using std::endl;


    //malloc/free与new/delete表达式的区别?
    //相同点: 都是用来申请堆空间
    //
    //不同点:
    // 1. malloc/free是库函数; new/delete是表达式
    // 2. malloc开空间时,并不会进行初始化;new表达式是可以进行初始化

    void test0()
    {
      int * p0;

      int * p1 = (int *)malloc(sizeof(int));//系统调用
      ::memset(p1, 0, sizeof(int));
      //bzero();
      *p1 = 10;
      printf("*p = %d ", *p1);

      free(p1);


      int * p2 = (int *)malloc(sizeof(int) * 10);

      free(p2);
    }

    void test1()
    {
      int * p1 = new int(1);
      cout << "*p1 = " << *p1 << endl;

      delete p1;

      int * p2 = new int[10]();//对于数组的申请需要加上[]
      //加上小括号是有初始化
      //不加小括号是不会进行初始化
      delete [] p2;
    }

    int main(void)
    {
      test0();
      test1();
      return 0;
    }


    函数重载

    #include <stdio.h>
    #include <iostream>
    using std::cout;
    using std::endl;

    //C++语言支持函数重载
    //实现原理: 名字改编(name mangling)
    //具体步骤: 当函数名称相同时,会根据
    //函数参数的类型、个数、顺序进行改编


    int add(int x, int y)
    {
      return x + y;
    }

    int add(int x, int y, int z)
    {
      return x + y + z;
    }

    double add(double x, double y)
    {
      return x + y;
    }

    double add(int x, double y)
    {
      return x + y;
    }

    double add(double x, int y)
    {
      return x + y;
    }

    int main(void)
    {
      int a = 3, b = 4, c = 5;
      double d1 = 1.1, d2 = 2.2;
      cout << "add(a, b) = " << add(a, b) << endl;
      cout << "add(a, b, c) = " << add(a, b, c) << endl;
      cout << "add(d1, d2) = " << add(d1, d2) << endl;

      printf("a = %d, b = %d ", a, b);

      return 0;
    }


    指针和引用

    #include <iostream>
    using std::cout;
    using std::endl;


    //引用于指针的区别?


    //相同点: 引用底层的实现还是指针, 引用于指针都有"地址"的概念
    //
    //不同点:
    // 1. 引用是一个变量的别名,必须要进行初始化
    // 指针是一个独立的实体,可以不进行初始化
    // 2. 引用不是一个独立的实体
    // 3. 引用一经绑定之后,就不会就再改变其指向;
    // 指针是很灵活的,可以改变指向

    void test0()
    {
      int number = 1;
      //引用是变量的别名
      int & ref = number;
      cout << "ref = " << ref << endl;
      cout << "number = " << number << endl;

      ref = 10;
      cout << ">> 修改引用之后:" << endl;
      cout << "ref = " << ref << endl;
      cout << "number = " << number << endl;
      cout << "&ref = " << &ref << endl
        << "&number = " << &number << endl;


      //int & ref2;//error 引用不能单独存在,必须要绑定到一个实体
      //引用必须要进行初始化
    }

    //值传递 ==> 复制
    #if 0
    void swap(int x, int y)
    {
      int temp = x;
      x = y;
      y = temp;
    }
    #endif

    //地址传递 ==> 值传递 ==> 复制
    void swap(int * px, int * py)
    {
      int temp = *px;
      *px = *py;
      *py = temp;
    }

    //引用作为函数的参数存在
    // 引用传递 ==> 没有复制的开销,
    //可以提高程序的执行效率,
    //传递参数的方式更加直观,自然
    void swap(int & x, int & y)
    {
      int temp = x;
      x = y;
      y = temp;
    }

    void test1()
    {
      int a = 3, b = 4;
      cout << "a = " << a << ", b = " << b << endl;
      swap(a, b);
      //swap(&a, &b);
      cout << "a = " << a << ", b = " << b << endl;
    }


    //引用还可以作为返回值存在

    int array[5] = {1, 2, 3, 4, 5};


    int func1()
    {
      int number = 5;
      return number;//会进行复制
    }

    int & getNumber(int idx)
    {
      return array[idx];//如果返回值是引用,不会进行复制
    }

    //不能返回一个局部变量的引用
    int & func2()
    {  //当函数执行完毕时,局部变量生命周期已经结束
      int number = 5;
      return number;
    }

    //不要轻易返回一个堆空间变量的引用
    //除非已经有了内存回收的策略
    int & func3()
    {
      int * p3 = new int(100);
      return *p3;
    }

    void test2()
    {
      int idx = 0;
      cout << "array[idx] = " << getNumber(idx) << endl;
      &getNumber(1);

      getNumber(idx) = 10;//左值:就是可以取地址
      cout << "array[idx] = " << getNumber(idx) << endl;

      //&func1();//error 右值(临时变量): 不可以取地址
      //func1() = 100;//error

      //int & ref = func2();
      //cout << "ref = " << ref << endl;//error

      int & ref2 = func3();
      cout << "ref2 = " << ref2 << endl;
      delete &ref2;

      int a = 3, b = 4, c = 5;

      c = a + func3() + b + c;//执行该表达式之后,就会发生内存泄漏
      cout << "c = " << c << endl;
    }


    int main(void)
    {
      test0();
      test1();
      test2();
      return 0;
    }


    external C 编译

    //对于C源码不希望按C++方式进行调用(不进行名字改编),
    // 按C的方式进行调用
    //
    //
    //C的代码要放在C++中运行(C与C++混合编程)

    #ifdef __cplusplus //该宏只会在C++的编译器中定义
    extern "C"
    { //都会用C的方式进行调用
    #endif

    int add(int x, int y)
    {
    return x + y;
    }

    #ifdef __cplusplus
    }//end of extern "C"
    #endif


    简答题:
    1. const关键字与宏定义的区别是什么?

    2. 引用于指针的区别是什么?

    3. malloc的底层实现是怎样的?free是怎么回收内存的?

    4. new/delete与malloc/free的区别是什么?


    inline函数


    //inline函数的功能与带参数的宏定义效果一样

    //尽量用inline函数替换带参数的宏定义

    #pragma once

    //inline函数可以有声明和实现,但是必须在同一文件
    //inline函数不能分成头文件和实现文件
    inline int add(int x, int y)
    { //一般不要放循环语句
    return x + y;
    }

    //......


    C++ 类型转换

    #include <iostream>
    using std::cout;
    using std::endl;

    void test0()
    {
      double val1 = 1.11;
      int val2 = (int)val1;
      int val3 = int(val1);

      cout << "val2 = " << val2 << endl;
      cout << "val3 = " << val3 << endl;
    }

    void test1()
    {
      double val1 = 1.11;
      int val2 = static_cast<int>(val1);
      cout << "val2 = " << val2 << endl;

      int * p1 = static_cast<int*>(malloc(sizeof(int)));
      *p1 = 10;
      free(p1);

      //const_cast/dynamic_cast/reinterpret_cast
    }

    int main(void)
    {
      //test0();
      test1();
      return 0;
    }


    struct 在C++中

    struct Example
    {
      //struct的默认访问权限是Public
      Example(int x)
      : _ix(_iy)
      , _iy(x)
      {
      }
      void setX(int ix)
      { _ix = ix; }

      void setY(int iy)
      { _iy = iy; }

      void print()
      {
        cout << "(" << _ix << "," << _iy << ")" << endl;
      }

    private:
      int _ix;
      int _iy;
    };


    C++中的string

    #include <string.h>

    #include <string>
    #include <iostream>
    using std::cout;
    using std::endl;

    void test0()
    {
      const char * pstr1 = "hello";// 文字常量区, 只读的
      const char * pstr2 = "world";//C风格字符串
      //*pstr1 = 'X';//error 不能进行修改

      //空间是否足够
      char * ptmp = new char[strlen(pstr1) + strlen(pstr2) + 1]();
      strcpy(ptmp, pstr1);
      strcat(ptmp, pstr2);
      cout << "ptmp = " << ptmp << endl;

      delete [] ptmp;

      //获取字符串的长度
      //strlen ==> 时间复杂度是O(N)

    }

    void test1()
    {
      //把C风格字符串转换成C++风格的字符串
      std::string s1 = "hello";
      std::string s2 = "world";

      //做字符串的拼接
      std::string s3 = s1 + s2;
      cout << "s3 = " << s3 << endl;
      s3 += "aaa";
      cout << "s3 = " << s3 << endl;


      //获取字符串的长度
      cout << "s3'size = " << s3.size() << endl;
      cout << "s3'length = " << s3.length() << endl;

      //把C++风格字符串转换成C风格字符串
      const char * pstr = s3.c_str();
      const char * pstr2 = s3.data();
      cout << "pstr = " << pstr << endl;
      cout << "pstr2 = " << pstr2 << endl;

      //遍历元素
      for(size_t idx = 0; idx != s3.size(); ++idx)
      {
        cout << s3[idx] << endl;//数组的下标进行访问
      }

      //&s3; 代表的是std::string类型的对象的首地址


      s3.append(3, 'j');
      cout << "s3 = " << s3 << endl;
      s3.append(s1);
      cout << "s3 = " << s3 << endl;
      s3.append("wangdao");
      cout << "s3 = " << s3 << endl;
      s3.append("shenzhen", 4);
      cout << "s3 = " << s3 << endl;

      //查找元素的用法
      size_t pos = s3.find("world");
      cout << "pos = " << pos << endl;
      std::string s4 = s3.substr(pos, 5);
      cout << "s4 = " << s4 << endl;

    }

    int main(void)
    {
      test0();
      test1();
      return 0;
    }


    构造函数和析构函数

    #include <iostream>
    using std::cout;
    using std::endl;

    class Point
    {
    public:
      #if 1
      //当没有显式定义构造函数时,系统会自动提供一个
      //默认构造函数
      Point()
      {
        _ix = 0;
        _iy = 0;
        cout << "Point()" << endl;
      }
      #endif

    #if 1
    //构造函数可以重载
    //
    //如果显式定义了有参构造函数时,系统就
    //不会再自动提供默认构造函数
    //
    //如果还希望通过默认构造函数创建对象,则必须
    //显式提供一个默认构造函数
    //
      Point(int ix, int iy)
      {
        _ix = ix;
        _iy = iy;
        cout << "Point(int,int)" << endl;
      }

      

      Point(int ix = 0, int iy = 0)
      : _ix(ix) //对于数据成员的初始化,都要放在初始化表达式之中进行
      , _iy(iy)
      {
        //_ix = ix;//赋值语句
        //_iy = iy;
        cout << "Point(int=0,int=0)" << endl;
      }


    #endif

      void print()
      {
        cout << "(" << _ix
        << "," <<_iy
        << ")" << endl;
      }

    // 析构函数没有返回值,函数名与类名相同,同时还需要在前面
    // 加上一个波浪号,与构造函数进行区分;
    // 析构函数没有形参, 析构函数只有一个
    //
    // 当一个对象的生命周期结束的时候,会自动调用析构函数
    //

      //系统提供的析构函数
      ~Point()
      {}

    #if 0
      ~Point()
      {
        cout << "~Point()" << endl;
      }
    #endif

    private:
      int _ix;
      int _iy;
    };

    int main(void)
    {
      //Point pt1(1, 2);
      //pt1.print();

      Point pt2;//调用无参(默认)构造函数
      pt2.print();

      return 0;
    }

    #include <iostream>
    using std::cout;
    using std::endl;

    class Point
    {
    public:
      Point(int ix = 0, int iy = 0)
      : _ix(ix)
      , _iy(iy)
      {
        cout << "Point(int=0,int=0)" << endl;
      }

    //系统提供的复制构造函数
    //问题1: 形参中的引用符号不能删除,如果删除,
    //会造成复制构造函数无穷递归调用,直到栈溢出,程序崩溃
    //
    //问题2: 形参中的const关键字可以去掉不?
    // 不可以去掉,如果去掉,当传递过来的参数是右值时,就会
    // 报错
    //Point(const Point rhs):
    //Point(Point & rhs)
    Point(const Point & rhs) //复制构造函数形式是固定的
    : _ix(rhs._ix)
    , _iy(rhs._iy)
    {
      cout << "Point(const Point & )" << endl;
    }

    void print()
    {
      cout << "(" << _ix
      << "," <<_iy
      << ")" << endl;
    }

    private:
      int _ix;
      int _iy;
    };

    //形参与实参都是对象(值传递),会调用复制构造函数
    void func1(Point pt)
    {
      cout << "pt = ";
      pt.print();
    }

    //函数的返回值是对象时,执行return语句
    //也会调用复制构造函数;但一般情况下,会
    //被编译器优化掉;如要要看到完整形式,需要
    //在编译时 加上编译选项 -fno-elide-constructors
    Point func2()
    {
      Point pt(11, 12);
      cout << ">> pt = ";
      pt.print();
      return pt;
    }


    int main(void)
    {
      int a = 3;
      int b = a;

      //int & ref = 1;//字面值常量, 非const引用不能绑定到右值
      const int & ref2 = 1;// const引用可以绑定到右值
      cout << "ref2 = " << ref2 << endl;

      Point pt1(1, 2);
      cout << "pt1 = ";
      pt1.print();

      //Point(const Point rhs);
      // const Point rhs = pt1;
      // Point(const Point rhs);
      // const Point rhs = pt1;
      Point pt2 = pt1;//调用复制(拷贝)构造函数
      cout << "pt2 = ";
      pt2.print();
      cout << "----" << endl << endl;

      func1(pt2);
      cout << "----" << endl << endl;

      func2();//临时对象, 右值

      Point pt3 = func2();//Point(Point & rhs);
      //非const引用无法绑定到右值
      //Point & rhs = func2();
      pt3.print();
      cout << "----" << endl << endl;
      func2().print();

      return 0;
    }


    程序内存区域

    #include <stdio.h>
    #include <string.h>

    #include <iostream>
    using std::cout;
    using std::endl;

    int a = 1;//全局静态区
    char * p1;//全局变量如果没有显式进行初始化,
    //系统也会设置默认值

    int test0(void)
    {
      int b = 2;
      const char * p2 = "hello,world";//文字常量区
      char str[] = "hello,world";//栈区
      //str = 0x1000;//str 常量

      char * p3;//野指针

      p3 = new char[20]();//堆区

      strcpy(p3, "hello,world");

      static int c = 100;//局部静态变量, 全局/静态区
      ++c;

      printf("sizeof(str) = %lu ", sizeof(str));
      printf("sizeof(p2) = %lu ", strlen(p2));

      printf("&a = %p ", &a);
      printf("&b = %p ", &b);
      printf("p1 = %p ", p1);
      printf("&p1 = %p ", &p1);
      printf("p2 = %p ", p2);
      printf("&p2 = %p ", &p2);
      printf("str = %p ", str);
      printf("p3 = %p ", p3);
      //*p3 = '1';//error 野指针
      printf("&p3 = %p ", &p3);
      printf("&c = %p ", &c);
      printf("address(hello,world) = %p ", "hello,world");
      printf("address(test0) = %p ", &test0);//程序代码区

      return 0;
    }

    int main(void)
    {
      test0();
      return 0;
    }


    默认参数

    #include <stdio.h>
    #include <iostream>
    using std::cout;
    using std::endl;

    //默认参数/缺省参数

    //一旦某个参数被设置了默认值,后面的所有的参数都要设置默认值
    //
    //默认参数的设置只能从右到左的顺序进行
    int add(int x = 0, int y = 0)
    {
      return x + y;
    }

    int add(int x, int y, int z)
    {
      return x + y + z;
    }

    int main(void)
    {
      int a = 3, b = 4, c = 5;
      cout << "add(a) = " << add(a) << endl;
      cout << "add(a, b) = " << add(a, b) << endl;
      cout << "add(a, b, c) = " << add(a, b, c) << endl;

      return 0;
    }


    拷贝构造函数 构造函数析构函数 深拷贝浅拷贝

    #include <string.h>
    #include <iostream>
    using std::cout;
    using std::endl;


    //代码风格是非常重要的


    //如果是自定义类类型,都要大写首字母
    class Computer
    {
    public://public成员可以在类之外访问
    //public成员称为类对外的接口、功能、服务

    //对成员函数采用驼峰方式进行命名
    void setBrand(const char * brand)
    {
      strcpy(_brand, brand);
    }

    void setPrice(double price)
    {
      _price = price;
    }

    //protected://保护成员不能在类之外访问
    void print()
    {
      cout << "brand:" << _brand << endl
      << "price:" << _price << endl;
    }

    //私有成员尽量放到类的底部
    private://私有的成员不能在类之外访问
      char _brand[20];//brand_ / m_brand
      double _price;
    };

    int main(void)
    {
      int a;

      Computer pc1;
      pc1.setBrand("Thinkpad");
      pc1.setPrice(8888);
      pc1.print();


      //pc1._price = 1000;//error

      return 0;
    }


    //类的声明
    class Computer
    {//class的默认访问权限是private的
    public:
      void setBrand(const char * brand);
      void setPrice(double price);
      void print();

    //通过private关键字表现封装的特性
    private://类对象占据的空间只与数据成员有关
    //成员函数存储在程序代码区, 不会占据对象的空间
      char _brand[20];
      double _price;
    };

    #include <string.h>
    #include <iostream>
    using std::cout;
    using std::endl;


    class Computer
    {
    public:
    Computer(const char * brand, double price)
    : _brand(new char[strlen(brand) + 1]()) //浅拷贝, 只传地址
    , _price(price)
    {
      strcpy(_brand, brand);
      cout << "Computer(const char *, double)" << endl;
    }

    void print()
    {
      cout << " brand:" << _brand << endl
      << " price:" << _price << endl;
    }

    //对象销毁的过程中会自动调用析构函数
    //
    //问题: 执行了析构函数就是销毁了对象

    #if 0
    void release()
    {
      delete [] _brand;
    }
    #endif

    ~Computer()
    { //析构函数的作用:是用来回收对象申请的资源
      if(_brand) {
        delete [] _brand;
        _brand = nullptr;//NULL
      }
      cout << "~Computer()" << endl;
    }

    private:
      char * _brand;
      double _price;
    };

    //Computer pc2("Xiaomi", 7500);

    int test0(void)
    {
      {
        Computer pc1("MateBook", 6666);
        cout << ">> pc1: " << endl;
        pc1.print();
      }

      cout << ">> pc2: " << endl;
      // pc2.print();

      //堆空间的对象的销毁,需要手动执行
      Computer * pc3 = new Computer("Thinkpad", 7777);
      cout << ">> pc3: " << endl;
      pc3->print();

      delete pc3;//不要忘了, 执行delete表达式的过程中,就会调用析构函数

      static Computer pc4("Macbook pro", 20000);
      cout << ">> pc4: " << endl;
      pc4.print();

      return 0;
    }

    void test1()
    {
      Computer * pc3 = new Computer("Thinkpad", 7777);
      cout << ">> pc3: " << endl;
      pc3->print();
      pc3->~Computer();//该语句被执行之后,对象是没有被销毁的
      delete pc3;
      }

    void test2()
    {
      Computer pc1("MateBook", 6666);
      cout << ">> pc1: " << endl;
      pc1.print();
      pc1.~Computer();//析构函数可以主动调用,但不推荐这样做
      //析构函数应该让其自动执行
      //pc1.release();
    }

    int main(void)
    {
      //test1();
      test2();
      return 0;
    }

    //系统提供的 已经不能满足需求
    #if 0
    Computer(const Computer & rhs)
    : _brand(rhs._brand)//浅拷贝, 只传地址
    , _price(rhs._price)
    {
      cout << "Computer(const Computer&)" << endl;
    }
    #endif
    Computer(const Computer & rhs)
    : _brand(new char[strlen(rhs._brand) + 1]())
    , _price(rhs._price)
    {
      strcpy(_brand, rhs._brand);
      cout << "Computer(const Computer&)" << endl;
    }

  • 相关阅读:
    mysql 45讲 索引的使用 09-11
    mysql 45讲 相关锁的概念 06-08
    mysql 45讲 深入浅出索引04-05
    mysql 45讲 概览 01-03
    AQS源码解析第二回
    面试相关-怎么实现限流功能
    人工智能必备数学基础:线性代数基础(2)
    Elasticsearch问题总结和解决方法
    spring boot中打印所有日志
    Java中Stream流里面的findFirst()和findAny()区别
  • 原文地址:https://www.cnblogs.com/Davirain/p/11788084.html
Copyright © 2011-2022 走看看