拷贝构造函数和赋值运算符的认识
- 拷贝构造函数生成新的类对象,而赋值运算符是给已有的对象重新赋值。
- 由于拷贝构造函数是直接构造一个新的类对象,所以在初始化这个对象之前不用检验源对象是否和新对象相同。而赋值运算符则需要这个操作,另外赋值运算中如果原来的对象中已有内存分配要先把内存释放掉。
- *注意:当类中有指针类型的成员变量时,一定要重写拷贝构造函数和赋值运算发,不要使用默认的。
//copy constructor 声明 string(const string&); //assign operator 声明 string& operator=(const string& rhs); //拷贝构造函数的实现 string::string(const string& another) { std::cout << "拷贝构造函数被调用:\n"; m_data = new char[strlen(another.m_data) + 1]; strcpy(m_data, another.m_data); } // 赋值运算 string& string::operator=(const string& rhs) { std::cout << "赋值运算符被调用:\n"; if (this == &rhs) return *this; delete[]m_data; m_data = new char[strlen(rhs.m_data) + 1]; strcpy(m_data, rhs.m_data); return *this; }
-
深拷贝、浅拷贝
说到拷贝构造函数,就不得不提深拷贝和浅拷贝。通常,默认生成的拷贝构造函数和赋值运算符,只是简单的进行值的复制。例如:上面的
Person
类,字段只有int
和string
两种类型,这在拷贝或者赋值时进行值复制创建的出来的对象和源对象也是没有任何关联,对源对象的任何操作都不会影响到拷贝出来的对象。反之,假如Person
有一个对象为int *
,这时在拷贝时还只是进行值复制,那么创建出来的Person
对象的int *
的值就和源对象的int *
指向的是同一个位置。任何一个对象对该值的修改都会影响到另一个对象,这种情况就是浅拷贝。深拷贝和浅拷贝主要是针对类中的指针和动态分配的空间来说的,因为对于指针只是简单的值复制并不能分割开两个对象的关联,任何一个对象对该指针的操作都会影响到另一个对象。这时候就需要提供自定义的深拷贝的拷贝构造函数,消除这种影响。通常的原则是:
- 含有指针类型的成员或者有动态分配内存的成员都应该提供自定义的拷贝构造函数
- 在提供拷贝构造函数的同时,还应该考虑实现自定义的赋值运算符
对于拷贝构造函数的实现要确保以下几点:
- 对于值类型的成员进行值复制
- 对于指针和动态分配的空间,在拷贝中应重新分配分配空间
- 对于基类,要调用基类合适的拷贝方法,完成基类的拷贝
摘自:https://blog.csdn.net/BostonRayAlen/article/details/93041395 , https://www.cnblogs.com/wangguchangqing/p/6141743.html
记录学习点滴,如有违规请告知。