【问题标题】:Ensuring that a member variable is moved, if the object is a rvalue如果对象是右值,则确保移动成员变量
【发布时间】:2015-08-21 13:15:09
【问题描述】:

请考虑以下代码:

class A
{
public:
    A(/* params */) {
        // Fill m_data depending on params
    }

    std::vector<double> get_data() const noexcept {
        return m_data;
    }

private:
    std::vector<double> m_data;
};

std::vector<double> get_data() {
    return A{/* suitable params */}.get_data();
}

我想要的是,m_data移动 到函数 get_data() 的调用者,即不应复制。

我怎么能确定是这种情况?显然,A{/* suitable params */} 是一个右值。因此,它的成员变量m_data 在这种情况下是一个右值。那么,再增加一个成员函数就够了吗

std::vector<double> get_data() && noexcept {
    return std::move(m_data);
}

【问题讨论】:

  • @Barry:答案部分在下面,小伙子:↓↓↓↓↓↓↓ 我知道你知道它在哪里,因为你在里面发帖了。
  • 您的原始版本的get_data 调用一个复制构造函数,它可能会抛出bad_alloc,在这种情况下noexcept 将调用std::terminate()。也许您只希望非复制右值重载为 noexcept

标签: c++ c++11 c++14 rvalue


【解决方案1】:

使用足够新的编译器(阅读:不是 MSVC 2013),您可以重载右值和左值。

class A {
  // ...
  std::vector<double> get_data() && noexcept {
    return std::move(m_data);
  }
  std::vector<double> get_data() const & { // not noexcept, could throw
    return m_data;
  }
  // ...
};

或者,左值版本可以返回一个对向量的 const 引用并且是 noexcept,但这意味着你暴露了你在某处有一个物理变量的事实,这会阻止你在未来的重构中改变它。

请注意,您不能拥有一个没有 ref 限定符的函数和另一个具有 ref 限定符的函数,否则它们具有相同的名称和参数。模棱两可,编译器应该抱怨。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-27
    • 2020-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多