【问题标题】:C++11 constructor argument: std::move and value or std::forward and rvalue referenceC++11 构造函数参数:std::move 和 value 或 std::forward 和 rvalue 引用
【发布时间】:2014-04-15 10:55:06
【问题描述】:

以下两个应该首选哪个,为什么?

struct X {
    Y data_;
    explicit X(Y&& data): data_(std::forward<Y>(data)) {}
};

struct X {
    Y data_;
    explicit X(Y data): data_(std::move(data)) {}
};

【问题讨论】:

  • POD 没有用户定义的构造函数!我更喜欢第二个,因为第一个不会绑定到左值。另外,第一个应该是std::forward&lt;Y&gt;(data)
  • 请将第一个中的std::forward 替换为std::movestd::forward 仅与模板参数结合使用才有意义。
  • forward添加了模板参数
  • @Praetorian 据我所知,POD 可以有用户定义的构造函数(!=聚合)。但是,不能有用户定义的默认、复制或移动构造函数(或 dtor)。
  • @dyp 我的印象是 POD 是一个聚合,其成员也是 POD,即要求比聚合更严格。目前无法检查...

标签: c++ c++11 move-semantics rvalue-reference copy-elision


【解决方案1】:

这两种变体在功能上有所不同。以下语句适用于第二个,但不适用于第一个:

Y y;
X x(y);

如果您正在寻找相同的功能,这两个变体应如下所示:

struct X
{
    Y data_;
    explicit X(const Y& data) : data_(data) { }
    explicit X(Y&& data) : data_(std::move(data)) { }
};

struct X
{
    Y data_;
    explicit X(Y data) : data_(std::move(data)) { }
};

第一个变体节省了一个 move 操作,而第二个变体写得更少。所以,答案是:只要你没有理由优化性能,就使用后者。

【讨论】:

  • 是否应该读作“第一个变体保存一个 copy 操作”? (也就是说,当我们有一个右值并且可以使用移动构造函数时,第二个变体仍然需要复制它的参数)
  • 如果我们有一个 rvalue,那么第二个变体中的参数 data 将使用 move constructor 构造,即对象将移动两次,首先从实参移入形参,然后从形参移入成员变量。与第一个变体相比,没有额外的复制操作。只有一个额外的移动操作
猜你喜欢
  • 2016-03-21
  • 2013-12-08
  • 2013-08-24
  • 2015-08-21
  • 2020-01-17
  • 2014-10-15
  • 1970-01-01
  • 2017-04-17
  • 2015-02-14
相关资源
最近更新 更多