"C++ Primer" 读书笔记 复制构造函数、赋值操作符与析构函数/重载操作符

复制构造函数

  我们知道,构造函数无非就是初始化一个类的函数:在不同的实参下如何将这个函数的数据成员初始化;只要创建该类的新对象,那么构造函数就一定会被执行。

  • 复制构造函数只有一个参数,即本类的引用。一般形参是const引用。
  • 如果不手动定义复制构造函数,则编译器会自动合成复制构造函数:执行逐个成员初始化,即所有的成员都相等。
  • 注意,默认构造函数(即无参构造函数)不一定存在,但是复制构造函数总会存在。
  • 复制构造函数在三种情况下被调用
  1. 当用一个对象去初始化同类型的另一个对象时,无论是C a = b; 还是 C a(b);都会调用;但是注意初始化和赋值不同,赋值不会调用到复制构造函数;
  2. 作为函数的形参时,在函数内部作用域里实际上是复制了一个新的对象副本,由复制构造函数生成,在时间上存在开销;使用引用传参而不是值传参将减少时间开销,再加一个const确保实参对象不会被修改,安全
  3. 函数return的值是该对象时,在调用函数的位置调用了复制构造函数,把函数局部作用域的东东拷到外面的作用域

默认构造函数  

  • 无论如何,类必须要有一个构造函数,如果用户不定义,那么编译器将自动生成,这就是默认构造函数:没有形参,内部也没有任何逻辑
  • 一旦用户自定定义了构造函数,任何形参都行,那么默认构造函数此时是没有的

 

析构函数  

  • 构造函数用于初始化一个对象;那么析构函数就是进行销毁对象的操作:释放内存、关闭打开的文件等
  • 没有参数,不能重载,不能显式调用,销毁对象时自动执行
    • 什么时候销毁对象?很好理解!和普通的变量一样:
      • 全局对象的生命周期和进程本身相同,存放在数据段,在进程结束时自动调用析构函数
      • 局部对象的生命周期就是其作用域,存放在栈中,跳出作用域时自动析构
      • new创建的对象存放在堆中,通过delete才能调用析构函数,否则一直占用内存!
  • 析构函数里一般只做一件事:delete之前new的对象       

 

赋值操作符

  • =是赋值操作符,用在类身上会发生什么?当然是把一个类的值赋值给另一个类咯。
  • 不要想当然!实际上这是对=操作符的重载,可以看作是一个函数:形参包括左操作数和右操作数,返回值是同一类类型的引用
  • 如果用户没有自己定义赋值操作符,那么合成赋值操作符将进行逐个成员赋值
  • 赋值操作符与复制构造函数是挂钩的,需要其中一个,另一个也同样需要被定义  

 

操作符重载

//重载操作符可以是某个类的成员函数,此时需注意限定作用域与隐含的this指针
my_class my_class::operator+(const my_class & A) const {
  my_class B;
  B->m_number = this->m_number + A.m_number;            
  return B;   
}

my_class& my_class::operator++(){
  ++this->m_number;
  return *this;
}

my_class& my_class::operator+=(const my_class &b){
  this->m_number += b->m_number;
  return *this;
}
// 重载操作符也可以是全局函数
my_class operator+(const my_class &a, const my_class &b ) { return my_class(a.m_num + b.m_num); }
  • 操作符重载的优先级、操作数、本来的用法不能改变,需要与其作为内置类型的重载操作符时一致
  • 当然不能有默认参数,不然操作数的数量就可变了
  • 箭头运算符->、下标运算符[]、函数调用运算符()、赋值运算符=只能以成员函数的形式重载
  • 重载操作符作为全局函数,必须在类的内部将该操作符设为友元

  

posted @ 2019-08-20 17:21  LiaoQian1996  阅读(94)  评论(0编辑  收藏  举报