#include <iostream>
class A {
public:
A(){};
A(A& b) { std::cout << "l\n"; };
};
class B {
public:
A x;
A p;
B() {}
B(A c) {
this->x = c;
this->p = c;
std::cout << "k\n";
}
};
int main(void) {
A b;
B x(b);
}
我现在知道这样的事情是不可能的,要在类B
中创建对象X和p
,我需要通过初始化器列表来创建它。所以只有像这样的方法才能奏效:
#include <iostream>
class A {
public:
A(){};
A(A& b) { std::cout << "l\n"; };
};
class B {
public:
A x;
A p;
B() {}
B(A c): x(c),p(c) {
std::cout << "k\n";
}
};
int main(void) {
A b;
B x(b);
}
我的问题是,第一种情况到底发生了什么?程序编译时没有错误,但没有(假定)调用复制构造函数。另外,根据我的理解,如果b的复制构造函数有,c
作为参数,那么复制构造函数也需要在c上调用(将b复制到c中),然后将c复制到其他一些复制构造函数中,等等。那么这难道不可能导致无休止的递归吗?
this->x=c
不会调用复制构造函数,它将调用复制赋值运算符。
A(A& b) { std::cout << "copy constructor\n"; };
A& operator=(A const& b) { std::cout << "copy assignment\n"; }
在执行构造函数的主体之前初始化成员。
如果不提供初始值设定项:
struct C {
A a;
C() = default;
};
则默认初始化memebrs。即:a
通过调用默认构造函数来构造。
如果在构造函数的主体中赋值:
struct D {
A a;
D(A x) {
a = x;
}
};
则首先默认初始化成员a
,然后由赋值覆盖。那有点浪费。
如果在memebr初始值设定项列表中提供非默认初始值设定项:
struct E {
A a;
E(A x) : a(x) {}
};
则成员a
未默认初始化。相反,它是通过制作x
的副本来构造的。
更多详细信息,请访问:https://en.cppreference.com/W/cpp/language/constructor
您的第一个版本在技术上是正确的。不清楚你说的“我知道现在这样的事情是不可能的”是什么意思。您在复制构造函数中看不到输出,因为它没有被调用。将cout
添加到复制分配中,以查看相应的输出。