【问题标题】:C++ Why was the copy constructor called?C++ 为什么要调用复制构造函数?
【发布时间】:2017-10-09 14:54:16
【问题描述】:
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&)”?

“A”的复制构造函数是什么时候调用的?而如果代码调用了拷贝构造函数,为什么我可以去掉拷贝构造函数而不产生编译错误呢?

【问题讨论】:

    标签: c++ c++11 copy-constructor


    【解决方案1】:

    B(A aa) 按值获取A,因此当您执行B b(a) 时,编译器调用复制构造函数A(const A&amp; a) 以在@ 的explicit 构造函数中生成名为aaA 实例987654328@.

    您可以删除复制构造函数并使其仍然有效的原因是编译器会在您还没有声明移动构造函数的情况下为您生成复制构造函数。

    注意:编译器生成的复制构造函数对于复杂的类通常是不够的,它执行一个简单的成员复制,所以对于复杂的元素或动态分配的内存你应该声明自己的。

    § 15.8.1

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

    【讨论】:

    • 编译器生成的复制构造函数应该对“复杂元素”没有问题,如果所述元素的类型已正确编写。
    【解决方案2】:

    复制发生的原因

    看看你的class Bc'tor:

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

    您通过收到A,在通话期间触发副本。

    如果您将其更改为(通知A &amp; 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 ) {}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-14
      • 2013-11-23
      • 2021-02-18
      • 2014-01-14
      • 1970-01-01
      • 1970-01-01
      • 2012-02-28
      相关资源
      最近更新 更多