C++ 编译如何选择调用哪个构造函数?

C++ 编译如何选择调用哪个构造函数?,c++,class,constructor,copy-constructor,default-copy-constructor,C++,Class,Constructor,Copy Constructor,Default Copy Constructor,这是我的密码 当我删除第11行时,输出是 A(0) B(0) A(1) 关于最后一行A1,为什么调用类A的第二个构造函数 #include <iostream> using namespace std; class A { public: A() { cout << "A(0)" << endl; } A(const A& a) { cout << "A(1)" << endl; } }; class B {

这是我的密码

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

A(0)
B(0)
A(1)
关于最后一行A1,为什么调用类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。为了复制成员a,它依次调用其复制构造函数,该构造函数打印A1。

编译器正在为您生成一个复制成员a的构造函数。为了复制成员a,它依次调用其复制构造函数,该构造函数打印A1。

,因为object2是用隐式复制构造函数B初始化的。隐式复制构造函数隐式复制类的所有数据成员,因此调用了复制构造函数a,它打印A1。

因为object2是用隐式复制构造函数B初始化的。隐式复制构造函数隐式复制类的所有数据成员,因此调用了A的复制构造函数,当

B(const B& b) { cout << "B(1)" << endl; }
这就是为什么您会看到一个名为的复制构造函数

当您不注释掉/删除时

B(const B& b) { cout << "B(1)" << endl; }
因此,将调用默认构造函数而不是复制构造函数。

B(const B& b) { cout << "B(1)" << endl; }
这就是为什么您会看到一个名为的复制构造函数

当您不注释掉/删除时

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

因此,调用默认构造函数而不是复制构造函数。

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

从C++ 20标准113.4.2复制/移动构造函数< /P> 14非联合类的隐式定义的复制/移动构造函数 X对其基础和成员执行成员复制/移动

类B的隐式定义的默认复制构造函数如下所示

B(const B& copy) : a(copy.a) {}
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的编译器隐式定义了调用类成员的复制构造函数的默认复制构造函数

从C++ 20标准113.4.2复制/移动构造函数< /P> 14非联合类的隐式定义的复制/移动构造函数 X对其基础和成员执行成员复制/移动

类B的隐式定义的默认复制构造函数如下所示

B(const B& copy) : a(copy.a) {}
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;
}

您遇到的问题与思考注释第11行意味着您删除了该构造函数有关

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

在本例中,您首先调用B的默认构造函数,它首先使用默认构造函数构造它的成员A。这将给出您看到的输出,其中由于成员初始化顺序,A的复制构造函数的主体在B的主体之前到达


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

您遇到的问题与思考注释第11行表示您已删除该构造函数有关

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

在本例中,您首先调用B的默认构造函数,它首先使用默认构造函数构造它的成员A。这将给出您看到的输出,其中由于成员初始化顺序,A的复制构造函数的主体在B的主体之前到达


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

您为什么感到惊讶?B的自动生成的复制构造函数调用A的复制构造函数。当行处于活动状态时,B的复制构造函数调用A的默认构造函数,因为A的任何构造函数都不是从B::B构造函数B和B中显式调用的。顺便说一句,您的复制构造函数应该是B构造函数B&B:ab.A{cout,您为什么感到惊讶?自动生成的B的复制构造函数调用A的复制构造函数。当行处于活动状态时,您的B的复制构造函数调用A的默认构造函数,因为A的任何构造函数都不是从B::Bconst B和中显式调用的。顺便说一句,您的复制构造函数应该是Bconst B&B:ab.A{cout