1

这是我的代码。

当我删除第 11 行时,输出是

A(0)
B(0)
A(1)

关于最后一行“A(1)”,为什么调用 A 类的第二个构造函数?

#include <iostream>

using namespace std;

class A {
public:
   A() { cout << "A(0)" << endl; }
   A(const A& a) { cout << "A(1)" << endl; }
};

class B {
public:
    B() : a() { cout << "B(0)" << endl; }
    // B(const B& b) { cout << "B(1)" << endl; }
private:
    A a;
};

int main() {
   B object1;
   B object2 = object1;
   return 0;
}
A(0)
B(0)
A(1)
4

5 回答 5

7

什么时候

B(const B& b) { cout << "B(1)" << endl; }

被注释掉/删除,编译器会为您生成一个复制构造函数。这个提供的复制构造函数将复制该类的所有成员,因此在这种情况下,它将删除一个看起来像的复制构造函数

B(const B& copy) : a(copy.a) {}

这就是为什么您会看到a调用的复制构造函数。

当您不注释掉/删除时

B(const B& b) { cout << "B(1)" << endl; }

你不复制a是因为你没有告诉它这样做。编译器所做的是通过将构造函数转换为

B(const B& b) : a() { cout << "B(1)" << endl; }

所以调用默认构造函数而不是复制构造函数。

于 2019-07-08T14:02:02.663 回答
1

编译器正在为您生成一个复制构造函数,它复制 member a。为了复制 member a,它依次调用它的复制构造函数,它会打印A(1)

于 2019-07-08T13:58:56.733 回答
0

因为object2是用 B 的隐式复制构造函数初始化的。隐式复制构造函数会隐式复制类的所有数据成员,因此调用 A 的复制构造函数,它会打印“A(1)”。

于 2019-07-08T14:01:45.530 回答
0

类 B 的编译器(带有注释的复制构造函数)隐式定义了调用类成员的复制构造函数的默认复制构造函数。

来自 C++ 20 标准(11.3.4.2 复制/移动构造函数)

14 非联合类 X 的隐式定义的复制/移动构造函数执行其基类和成员的成员复制/移动...

类 B 的隐式定义的默认复制构造函数看起来像

B( const B &b ) : a( b.a )
{
}

这是一个演示程序

#include <iostream>

using namespace std;

class A {
public:
   A() { cout << "A(0)" << endl; }
   A(const A& a) { cout << "A(1)" << endl; }
};

class B {
public:
    B() : a() { cout << "B(0)" << endl; }
    // An analogy of the implicitly declared copy constructor
    B(const B& b) : a( b.a ){}
private:
    A a;
};

int main() {
   B object1;
   B object2 = object1;
   return 0;
}

程序输出将与删除编译器隐式生成的复制构造函数对应的类 B 的复制构造函数一样。

A(0)
B(0)
A(1)
于 2019-07-08T14:06:53.317 回答
0

您遇到的问题与注释掉第 11 行的想法有关,这意味着您已经删除了该构造函数。

在 C++ 中,如果您最终使用它们,会自动生成几个构造函数,即使您自己没有声明它们也是如此。与 B 中注释掉的构造函数具有相同签名的复制构造函数就是其中之一。

在您的情况下,您最终首先调用 B 的默认构造函数,它首先也使用默认构造函数构造它的成员 A。这应该给出您看到的输出,由于成员初始化排序,A 的复制构造函数的主体在 B 的主体之前到达。

然后,使用赋值运算符创建一个 B 类型的新对象,该运算符隐式调用 B 现在生成的复制构造函数。这意味着 A 的复制构造函数也被调用,这是 B 的复制构造函数如何自动生成的规则。在 A 的复制构造函数未注释的情况下,它会在打印输出中被调用。

于 2019-07-08T14:08:55.167 回答