c++ - 尽管有非默认构造函数参数,但在 const 引用成员上调用默认构造函数

标签 c++ c++11 constructor initialization object-initializers

下面是一些基本的 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

我的问题是输出的第一行(考虑到第一行,所有其他的都有意义)。我正在初始化 B() 中的成员 _a : _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;
    }

关于c++ - 尽管有非默认构造函数参数,但在 const 引用成员上调用默认构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34830219/

相关文章:

c++ - 对象 vector - 如何向构造函数发送参数?

java - 有没有一种方法可以调用从没有自己的构造函数的子类获取参数的父类构造函数?

c++ - 用cmake构建比特币

c++ - 以漂亮的方式打印二叉树

C++ 为什么它不是同一个地址(指针)

c++ - 为什么 accumulate 的并行版本会慢得多?

c++ - 锁定的 'vector' 文件出错

c++ - 在 for 循环中声明的指向(本地)对象的指针范围

c++ - std::vector of objects/pointers/smart pointers to pass objects (bus error: 10)?

javascript - 在JavaScript中, "return"在函数构造函数中做什么