首页 > 解决方案 > 为什么不调用成员变量的移动构造函数?

问题描述

考虑以下类。如果我自己实现移动构造函数如下,为什么 bar 成员b不移动而是复制?但是如果我使用默认的移动构造函数,那么b就会被移动。为什么b(rhs.b)不叫bar(bar&&)

我将 g++ 9.2.1 与 --std=c++11 一起使用。

class bar {
public:
    bar() { cout << "bar constructor" << endl; }
    bar(const bar& rhs) { cout << "bar copy constructor" << endl; }
    bar(bar&& rhs) { cout << "bar move constructor" << endl; }
};

class foo {
    bar b;
public:
    foo() { cout << "foo constructor" << endl; }
    foo(const foo& rhs) { cout << "foo copy constructor" << endl; }
    // foo(foo&& rhs) = default;
    foo(foo&& rhs) : b(rhs.b) { cout << "foo move constructor" << endl; } // my version
    //               ^^^^^^^^
};

foo f;
foo g = std::move(f);

标签: c++c++11rvaluelvaluemove-constructor

解决方案


为什么b(rhs.b)不叫bar(bar&&)

因为rhs.b是一个左值,并且右值引用不绑定到值。结果——并且因为左值引用确实绑定到值——重载bar(const bar&),即复制构造函数,被选择而不是bar(bar&&)

为了选择移动构造函数,您需要在初始化成员时用 ( )标记rhs.b为“可移动” :<utility>std::move()foob

foo(foo&& rhs): b(std::move(rhs.b)) { /* ... */ }
                  ^^^^^^^^^

这是将表达式rhs.b转换为xvalue的强制转换,即绑定到rvalue引用的 rvalue 。所以,这次选择了移动构造函数。

但是如果我使用默认的移动构造函数,那么b就会被移动。

默认移动构造函数执行按成员移动。


推荐阅读