2017-10-09 103 views
3
class A { 
public: 
    A() {} 
    A(const A& a) { cout << "A::A(A&)" << endl; } 
}; 

class B { 
public: 
    explicit B(A aa) {} 
}; 

int main() { 
    A a; 
    B b(a); 
    return 0; 
} 

为什么打印“A :: A(A &)”?C++为什么要调用复制构造函数?

何时调用“A”的复制构造函数?如果代码调用复制构造函数,为什么我可以删除复制构造函数而不会产生编译错误?

回答

12

B(A aa)需要一个A通过值,所以当你执行B b(a)编译器调用拷贝构造函数A(const A& a)生成名为aa中的A实例explicit构造函数B

您可以删除复制构造函数并使其仍然有效的原因是,如果您还没有声明移动构造函数,编译器将为您生成一个复制构造函数。

注意:编译器生成的拷贝构造函数通常不足以满足复杂的类,它执行简单的成员智能拷贝,因此对于复杂元素或动态分配的内存,您应该声明自己的。

§15.8.1

如果类定义不明确声明拷贝构造函数,非明确的一个是隐式声明。 如果类定义声明移动构造函数或移动赋值运算符,则隐式声明的复制 构造函数被定义为已删除;否则,它被定义为默认(11.4)。如果 类具有用户声明的复制赋值运算符或用户声明的析构函数或赋值运算符,则不推荐使用后一种情况。

+0

编译器生成的拷贝构造函数对于“复杂元素”应该没有问题,如果所述元素是一种已被正确写入的类型。 – juanchopanza

7

为什么拷贝发生

看看你class B c'tor:

class B { 
public: 
    explicit B(A aa) {} 
}; 

您可以通过获得A,在通话过程中触发副本。

如果你必须将其更改为(通知A & aa):

class B { 
public: 
    explicit B(A & aa) {} 
}; 

世上本没有任何副本...

默认的拷贝构造函数

当您删除c'tor,编译器会为你生成一个这样的代码:

首先,你应该明白,如果你没有声明一个 的构造函数,编译器会给你一个隐含的。隐含的 拷贝构造函数执行源对象的成员方式拷贝。

默认c'tor等同于:

MyClass::MyClass(const MyClass& other) : 
    x(other.x), c(other.c), s(other.s) {} 
相关问题