【问题标题】:Unexpected default constructor call when using move semantics使用移动语义时意外的默认构造函数调用
【发布时间】:2022-01-12 16:53:57
【问题描述】:

我有两段相似的代码。第一个版本意外调用了默认构造函数,而第二个版本没有。它们都按预期分别调用了移动运算符/移动构造函数。

class MyResource
{
public:
    MyResource() : m_data(0) { std::cout << "Default Ctor" << std::endl; }
    MyResource(int data) : m_data(data) { std::cout << "Int Ctor" << std::endl; }

    MyResource(MyResource const& other) = delete;
    MyResource& operator=(MyResource const& other) = delete;

    MyResource(MyResource&& other) noexcept : m_data(other.m_data) { std::cout << "Move Ctor" << std::endl; }
    MyResource& operator=(MyResource&& other) noexcept { std::cout << "Move Op" << std::endl; m_data = other.m_data; return *this; }

    ~MyResource() { std::cout << "Dtor" << std::endl; }

private:
    int m_data = 0;
};

class MyWrapper
{
public:
    MyWrapper(MyResource&& resource)
        // : m_resource(std::move(resource)) // Version 2
    {
        // m_resource = std::move(resource); // Version 1
    }

private:
    MyResource m_resource;
};

我的测试用法是:

MyWrapper* wrapper = new MyWrapper(MyResource(1));
delete wrapper;

使用版本 1,我得到:

Int Ctor
默认Ctor
移动操作
Dtor
管理员

虽然版本 2 输出:

内测
移动角色
Dtor
管理员

造成这种差异的原因是什么?
为什么版本 1 会调用默认构造函数?

【问题讨论】:

    标签: c++ move-semantics


    【解决方案1】:

    在构造体运行之前初始化成员。一个更简单的例子:

    #include <iostream>
    
    struct foo {
        foo(int) { std::cout << "ctr\n";}
        foo() { std::cout << "default ctr\n";}
        void operator=(const foo&) { std::cout << "assignment\n"; }
    };
    
    struct bar {
        foo f;
        bar(int) : f(1) {}
        bar() {
            f = foo();
        }
    };
    
    int main() {
        bar b;
        std::cout << "---------\n";
        bar c(1);
    }
    

    Output:

    default ctr
    default ctr
    assignment
    ---------
    ctr
    

    您不能在构造函数的主体中初始化成员!如果您不提供初始值设定项,无论是在成员初始值设定项列表中还是作为类内初始值设定项,则默认构造 f。在构造函数主体中,您只能分配给已经初始化的成员。

    【讨论】:

      猜你喜欢
      • 2021-12-12
      • 2016-12-16
      • 2012-10-17
      • 1970-01-01
      • 1970-01-01
      • 2020-11-22
      • 1970-01-01
      相关资源
      最近更新 更多