1.复制构造函数可用于:
(1)根据另一个同类型的对象显示或隐式初始化一个对象
string str1="test"; //隐式
string str2=str1; //显示
str1为先调用string的字符串形参的构造函数,创建一个临时对象,然后,使用string复制构造函数将str1初始化为那个临时对象的副本。
(2)复制一个对象,将它作为实参传给一个函数
(3)从函数返回时复制一个对象
当形参为非引用类型的时候,将复制实参的值。类似地,以非引用类型作返回值时,将返回return语句中的值的副本。
(4)初始化顺序容器中的元素
vector<string> svec(5);
编译器首先使用string默认构造函数创建一个临时值来初始化svec,然后使用复制构造函数将临时值复制到svec的每个元素。
(5)根据元素初始化式列表初始化数组元素
如果没有为类类型数组提供元素初始化式,将使用默认构造函数初始化每个元素。然而,如果使用常规的花括号括住的数组初始化列表来提供显示元素初始化式,则使用复制初始化来初始化每个元素。
2.合成的复制构造函数
如果我们没有定义复制构造函数,编译器就会为我们合成一个。然而,有些类必须对复制对象时发生的事情加以控制。这样的类经常有一个数据成员是指针,或者有成员表示在构造函数中分配的其他资源。这样的情况下,我们必须定义复制构造函数。
class Foo
{
public:
Foo(); //default constructor
Foo(const Foo&); //copy constructor
}
3.禁止复制
(1)可以将类显示声明其复制构造函数为private
(2)如果连友元和成员中的复制也禁止,就可以声明一个private复制构造函数,但不对其定义。
声明而不定义成员函数是合法的,但是,使用未定义成员的任何尝试将导致链接失败。通过声明(但不定义)private复制构造函数,可以禁止任何复制类类型对象的尝试:用户代码中复制尝试将在编译时标记为错误,而成员函数和友元中的复制尝试将在链接时导致错误。
4.赋值运算符
(1)类也有合成的赋值运算符,然而,类也可以定义自己的赋值运算符。一般而言,如果类需要复制构造函数,它也会需要赋值运算符。
5.析构函数
(1)如果类需要析构函数,则他也需要赋值运算符和复制构造函数,这个规则称为“三法则”。
(2)析构函数和复制构造函数或者赋值运算符的一个最重要的区别就是,即使我们编写了自己的析构函数,也会调用合成析构函数。
6.复制构造函数和赋值运算符的区别
复制构造函数只在对象初始化时才被调用,无返回值。而赋值运算符是将一个现存的对象赋予新的值时被调用,有返回值。