高级程序设计

6 - 拷贝构造函数

2020-02-27 15:40 CST
2020-03-14 22:29 CST
CC BY-NC 4.0

拷贝构造函数

若一个构造函数的参数类型为本类地引用,则称它为拷贝构造函数。

在创建一个对象时,若用另一个同类型地对象对其初始化,将会调用对象类中的拷贝构造函数。

在三种情况下,会调用类的拷贝构造函数:

  • 创建对象时显示指出;
  • 把对象作为值参数传给函数时;
  • 把对象作为函数的返回值时。

隐式拷贝构造函数

在程序中如果没有为某个类提供拷贝构造函数,则编译器将会为其生成一个隐式拷贝构造函数。

隐式拷贝构造函数将逐个成员进行拷贝初始化。

  • 对于非对象成员:它采取通常的拷贝操作;
  • 对于对象成员:则调用成员对象类地拷贝构造函数来对成员对象进行初始化。

自定义拷贝构造函数

一般情况下,编译程序提供的隐式拷贝构造函数的行为足以满足要求,类中不需要自定义拷贝构造函数。

但在一些特殊情况下,必须要自定义拷贝构造函数,否则将会产生设计者未意识到的严重的程序错误。

注意:自定义的拷贝构造函数默认调用的是成员对象类的默认构造函数来对成员对象初始化。如果需要调用自定义的拷贝构造函数,需要在对象初始化表中显式指出。

例如:

class String {
 private:
  int len;
  char* str;
  // ......
}

如果没有显示定义拷贝构造函数,编译器构造的隐式拷贝构造函数会直接复制char*指针的值,使得两个字符串指向同一块内存区域。

带来的问题:

  • 如果对一个对象修改之后修改了这块空间的内容,则另一个对象将会受到影响。
  • 当两个对象消亡时,将会分别去调用它们的析构函数,这会使得同一块内存区域将被归还两次,从而导致运行错误。
  • 当两个对象中有一个消亡,另一个还没有消亡时,则会出现使用已被归还的空间的问题。