首页 > 代码库 > 13.1 复制构造函数

13.1 复制构造函数

首先,复制构造函数本质还是构造函数,只不过是什么时候使用不同,通常在复制初始化的时候调用(直接初始化也有可能调用,后面再提)。

定义:复制构造函数只有单个对本类对象引用的形参(常用const修饰)。 

class Test(){public:   Test(const Test& t) {}};

 

string null_book = "9-999-99999-9“;    //复制初始化string book(10,a);                   //直接初始化string empty_copy = string();          //复制初始化string empty_direct;                   1//直接初始化

从上面的例子可看出复制初始化和直接初始化最直接的区别在于是不是用”=“,实际的过程如何呢?

创建null_book时,编译器调用接受C风格字符串形参的string的构造函数,创建一个临时对象,然后再使用复制构造函数用将null_book初始化为那个临时对象的副本。

而上面的例子中的直接初始化直接调用相对应形参的构造函数即可,例外的是 string empty_direct2(empty_direct),这是个直接初始化,但调用复制构造函数,直接生成副本。

 

通常编译器会进行优化,比如

string word(”abcd“);string word = "abcd";

编译器注意到直接初始化与复制初始化达到的效果一样,所以将后者优化成了前者。

但是到直接初始化与复制初始化仅在低级别优化上存在差异。然而对于

  • 不支持复制的类型
  • 使用非explicit构造函数

的时候,它们有着本质差别:

ifstream file1("filename");ifstream file2 = "filename";

显然后者是错误的,”=“意味着复制初始化,而ifstream不允许复制。

vector<int> v1(42);   //okvector<int> v2 = 42;  //error vector的复制构造函数是private

注意前者是直接初始化,但是其过程是:

  使用int默认构造函数创建创建一个临时值来初始化svec,然后使用复制构造函数将临时值复制到svec的每个元素。看起来前一步很多余,所以

  作为一般规则,除非你想使用容器元素的默认初始值,更有效的办法是,分配一个空容器并将已知元素的值加入容器。

复制构造函数用于:

  • 用另一个对象初始化(显式&隐式)一个对象。
  • 返回一个复制的对象。
  • 作为实参传给函数(该过程复制了其对象)。
  • 顺序容器初始化
  • 根据元素初始化列表初始化数组元素