#include <bits/stdc++.h> using namespace std ; class Student { public: int NO ; string name ; explicit Student ( const int _NO , const string _name ) : NO ( _NO ) , name ( _name ) { cout << endl << "构造函数" << endl ; } void display () const { cout << endl << "NO : " << NO << "\t" << name << endl ; } ~Student () noexcept {} } ; int main () { Student One ( 1 , string ( "Jack" ) ) ; One.display () ; Student Two ( One ) ; // 拷贝一个副本 Two.display () ; Student Three = One ; // 拷贝一个副本 Three.display () ; vector < Student > P ; // 放进容器会调用拷贝构造函数 P.push_back ( One ) ; P[0].display () ; vector < Student* > Q ; Q.push_back ( &One ) ; // 这里没有调用 拷贝构造函数.......因为是指针 Q[0]->display () ; One.name = string ( "Marry" ) ; // 对指针的操作会作用到原来的内存上 Q[0]->display () ; return 0 ; }
C++的类有默认的拷贝构造函数,和构造函数一样,如果程序员不声明,编译器自动生成。
容易错的几点是:
1. 容器中放入对象实体,会调用拷贝构造函数
2. 容器中放入对象实体的指针,不会调用拷贝构造函数,因为指针只是地址
3. 容器的一些函数,参数上是 const 类型的,所以,如果自己写拷贝构造函数,参数必须是 const 类型的。
例如, C++ 的 vector :
push_back ( const value_type & )要求是 const 类型。
C++ 11 还支持右值引用, push_back ( value_type && )
4. 加 const 可以防止拷贝过程中源对象被修改
5. 加 & 是引用,为了减少拷贝构造函数,因为如果不加引用 &, 传入的参数本身就是一个副本,也要调用拷贝构造函数,所以会无限调用下去
6. 对象实体很大的情况,不建议用拷贝构造函数,开销太大。可以选择用指针,只需要保存一个地址,而且是基类的情况下还可以借助指针实现多态,但指针的操作都是在源对象上操作,这点要注意。
7. 拷贝构造函数,默认先找非 const 类型,再找 const 类型
#include <bits/stdc++.h> using namespace std ; class Student { public: int NO ; string name ; explicit Student ( const int _NO , const string _name ) : NO ( _NO ) , name ( _name ) { cout << endl << "构造函数" << endl ; } void display () const { cout << endl << "NO : " << NO << "\t" << name << endl ; } // vector // push_back ( const value_type & ) Student ( const Student &One ) { // 容器 push_back 参数是 const 类型 this->NO = One.NO ; this->name = One.name ; cout << endl << "参数是 const类型 的拷贝构造函数被调用了" << endl ; } Student ( Student &One ) { // explicit this->NO = One.NO ; this->name = One.name ; cout << endl << "参数是 普通数据类型 的拷贝构造函数被调用了" << endl ; } Student ( Student *One ) { this->NO = One->NO ; this->name = One->name ; cout << endl << "参数是 指针类型 的拷贝构造函数被调用了" << endl ; } ~Student () noexcept {} } ; int main () { Student One ( 1 , string ( "Jack" ) ) ; One.display () ; Student Two ( One ) ; // 拷贝一个副本 Two.display () ; vector < Student > P ; // 放进容器会调用拷贝构造函数 P.push_back ( One ) ; P[0].display () ; vector < Student* > Q ; Q.push_back ( &One ) ; // 这里没有调用 拷贝构造函数.......因为是指针 Q[0]->display () ; One.name = string ( "Marry" ) ; // 对指针的操作会作用到原来的内存上 Q[0]->display () ; return 0 ; }