尽管非默认构造函数参数,也会在const引用成员上调用默认构造函数

汉斯·罗格曼

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

我的问题是输出的第一行(所有其他的在第一行都有意义)。我初始化成员_aB() : _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?

亚曼·齐鲁扬(Armen Tsirunyan)

每个类型B的对象实际上都有两个类型A的子对象。一个是基类子对象,另一个是_a成员子对象。您调用了该成员的构造函数,但是基类子对象是默认初始化的,因为您没有在初始化列表中显式调用它的构造函数。

您可以通过以下方法做到这一点:

B() : A(arguments) //<--initialize the base-class subobject
    , _a(std::move(A(10))) {
        cout << "Called B()" << endl;
    }

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在C结构上调用默认构造函数

来自分类Dev

如何为成员变量调用非默认构造函数?

来自分类Dev

默认移动构造函数和引用成员

来自分类Dev

构造函数默认参数

来自分类Dev

非内联构造函数中的默认参数

来自分类Dev

结构中的默认成员值或默认构造函数参数?

来自分类Dev

std::map 在 [] 上调用默认构造函数,在 insert() 上调用复制构造函数

来自分类Dev

C ++ 11:使用非静态成员函数作为类构造函数中的默认参数

来自分类Dev

程序调用默认构造函数?

来自分类Dev

声明成员对象而不调用其默认构造函数

来自分类Dev

为什么移动构造函数的成员需要默认构造函数?

来自分类Dev

带互斥成员的默认移动构造函数

来自分类Dev

尽管覆盖了默认结构,但仍使用结构默认构造函数

来自分类Dev

防止const类函数在引用成员上调用非const类函数

来自分类Dev

不能引用默认构造函数

来自分类Dev

C ++调用默认构造函数而不是复制构造函数

来自分类Dev

尝试访问php中的父构造函数时,在PHP的非对象上调用成员函数query()

来自分类Dev

constexpr默认的默认构造函数

来自分类Dev

在Julia中构建非默认构造函数

来自分类Dev

非默认构造函数的C ++继承

来自分类Dev

默认移动构造函数

来自分类Dev

默认移动构造函数

来自分类Dev

多个默认构造函数

来自分类Dev

缺少默认构造函数

来自分类Dev

数组默认构造函数

来自分类Dev

默认移动构造函数

来自分类Dev

java默认构造函数

来自分类Dev

构造函数不能采用非const引用

来自分类Dev

没有调用C ++默认构造函数