1、复制构造函数的特点
- 只有一个参数,即对同类对象的引用
- 形如 X::X( X& )或X::X(const X &), 二者选一(后者能以常量对象作为参数)。即:形参要么是 对同类对象的引用,要么是对同类对象的常量引用。
- 如果没有定义复制构造函数,那么编译器生成默认复制构造函数。默认的复制构造函数完成复制功能。
注意:一个类中一定会有复制构造函数,要么是自己写的要么是编译器自动生成的,这与默认构造函数有所不同。编译器自动生成的复制构造函数完成的是对象间的拷贝工作。程序员自己写的复制构造函数完成的并不一定是对象间的复制工作,虽然道理上它应该完成对象间的复制工作,这取决于程序员自己。
2、复制构造函数起作用的三种情况
- 当用一个对象去初始化同类的另一个对象时。
- 如果某函数有一个参数是类 A 的对象,那么该函数被调用时,类A的复制构造函数将被调用。
- 如果函数的返回值是类A的对象时,则函数返回时,A的复制构造函数被调用。
//情况一:
Complex c2(c1);
Complex c2 = c1; //初始化语句,非赋值语句
//情况二:
class A
{
public:
A() { };
A( A & a) {
cout << "Copy constructor called" <<endl;
}
}
void Func(A a1){ }
int main(){
A a2;
Func(a2);
return 0;
}
//情况三
class A
{
public:
int v;
A(int n) { v = n; };
A( const A & a) {
v = a.v;
cout << "Copy constructor called" <<endl;
}
};
A Func() {
A b(4);
return b;
}
int main() {
cout << Func().v << endl; return 0;
}
注意:对象间赋值并不导致复制构造函数被调用。
class CMyclass {
public:
int n;
CMyclass() {};
CMyclass( CMyclass & c) { n = 2 * c.n ; }
};
int main() {
CMyclass c1,c2;
c1.n = 5; c2 = c1; CMyclass c3(c1); //对象间赋值
cout <<"c2.n=" << c2.n << ",";
cout <<"c3.n=" << c3.n << endl;
return 0;
}
输出: c2.n=5,c3.n=10
3、常量引用的使用
void fun(CMyclass obj_ ) {
cout << "fun" << endl;
}
这样的函数,调用时生成形参会引发复制构造函数调用,开销比较大。所以可以考虑使用 CMyclass & 引用类型作为参数。如果希望确保实参的值在函数中不应被改变,那么可以加上const 关键字。
void fun(const CMyclass & obj) {
//函数中任何试图改变 obj值的语句都将是变成非法
}
4、常量引用作为函数形参的好处:
- 节省复制拷贝函数被调用的开销。
- 防止原始数据被意外的修改。