这是一些基本的C ++代码大纲:
#include <cstdlib>
#include <iostream>
#include <thread>
using namespace std;
class M {
public:
M() = default;
~M() {
cout << "Called ~M" << endl;
}
};
class A {
public:
A(int z) : _z(z) {
cout << "Called A(int z)" << endl;
this_thread::sleep_for(chrono::milliseconds(1000));
}
A() {
cout << "Called A()" << endl;
this_thread::sleep_for(chrono::milliseconds(1000));
}
A(const A& a) {
cout << "Called A(const A& a)" << endl;
_z = a._z;
}
A(const A&& a) {
cout << "Called A(const A&& a)" << endl;
_z = a._z;
}
A& operator=(const A& a) {
cout << "Called A& operator=(const A& a)" << endl;
if (&a != this) {
cout << "Executed A& operator=(const A& a)" << endl;
}
}
virtual ~A() {
cout << "Called ~A" << endl;
}
int poll() const { return _z; }
private:
M _m;
int _z = 300;
};
class B : public A {
public:
// _a(10)
B() : _a(std::move(A(10))) {
cout << "Called B()" << endl;
}
virtual ~B() {
cout << "Called ~B" << endl;
}
private:
const A& _a;
};
int main(int argc, char** argv) {
B b;
A* aPtr = &b;
A& aRef = (*aPtr);
cout << aRef.poll() << endl;
return 0;
}
从上面的设置中,我得到以下输出:
Called A()
Called A(int z)
Called ~A
Called ~M
Called B()
300
Called ~B
Called ~A
Called ~M
我的问题是输出的第一行(所有其他的在第一行都有意义)。我初始化成员_a
中B() : _a(std::move(A(10)))
,这是被迫的_a
是const引用成员。带有int参数的CTOR也将被调用,但是为什么在A上调用默认的CTOR?为什么不动CTOR?因此,临时对象似乎只是被构造和破坏了,没有真正的动作发生(从稍后的300输出可以看出)。
现在,这个问题似乎与移动本身无关,而与const引用成员周围的行为有关。因为如果我将初始化列表更改为:B(): _a(10)
我会遇到相同的问题:默认情况下,默认对象将分配给const引用成员,并且初始化列表中的参数将被忽略。所以B(): _a(10)
我得到:
Called A()
Called A(int z)
Called B()
300
Called ~B
Called ~A
Called ~M
基本上第一行为什么是默认构造函数?以及如何更改代码,以便显示初始化中的10而不是默认中的300?
每个类型B的对象实际上都有两个类型A的子对象。一个是基类子对象,另一个是_a
成员子对象。您调用了该成员的构造函数,但是基类子对象是默认初始化的,因为您没有在初始化列表中显式调用它的构造函数。
您可以通过以下方法做到这一点:
B() : A(arguments) //<--initialize the base-class subobject
, _a(std::move(A(10))) {
cout << "Called B()" << endl;
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句