返回值或右值引用? [英] Return value or rvalue reference?

查看:490
本文介绍了返回值或右值引用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Scott Meyer的新书中,他提出了一个用于右值引用限定符的示例用法,它看起来像这样:

  class Widget {
private:
DataType values;

public:
DataType& data()& {return values; }
DataType data()&&& {return std :: move(values); } //为什么DataType?
};

这样:

  auto values = makeWidget()。data(); 

move-constructs 构建它。



为什么rvalue-ref限定 data()返回 DataType 而不是 DataType&&& auto 仍会推导 DataType (尽管 decltype(auto)不会 - 但这不可能是更喜欢返回一个值,而不是一个ravlue ref的唯一原因)。 个高度投票的回答返回一个右值引用,这在我的概念上更有意义。

解决方案

  DataType data()&& {return std :: move(values); } //为什么DataType? 

auto values = makeWidget()。data();

保存返回值的临时变量将通过移动构造函数初始化,然后临时初始化值 code> move(values)



< ,但由于 makeWidget()。data()是一个右值(prvalue to be exactly),移动构造函数被再次调用 - 以temporary作为参数。



现在考虑 复制-elision : :


当没有绑定到任何引用的无名临时数据库将被移动
或复制到相同cv非限定类型的对象中,则省略
copy / move。当构建临时时,它是
直接构建在存储中,否则将被移动
或复制到。当无名的临时变量是返回
语句的参数时,这个复制elision的变体称为RVO,返回值
优化。


因此,第二个动作(可能)完全被省略,只剩下一个 - 我们本来应该有的,返回类型是右值引用。



返回右值引用的问题是,如果我们写

  auto& values = makeWidget()。data(); 

将悬挂为绑定x值到参考不延长任何时间的寿命。当我们返回对象类型时,临时生存期被延长。


In Scott Meyer's new book, he proposes an example usage for rvalue reference qualifiers that looks something like this:

class Widget {
private:
    DataType values;

public:
    DataType& data() &  { return values; } 
    DataType  data() && { return std::move(values); } // why DataType?
};

So that:

auto values = makeWidget().data();

move-constructs values instead of copy-constructing it.

Why does the rvalue-ref-qualified data() return DataType instead of DataType&&? auto would still deduce DataType in that case (although decltype(auto) wouldn't - but that can't be the only reason to prefer to return a value instead of an ravlue ref). This highly voted answer returns an rvalue ref, which makes more sense conceptually to me.

解决方案

DataType data() && { return std::move(values); } // why DataType?

auto values = makeWidget().data();

The temporary that holds the return value will be initialized through the move-constructor, copy-initialized from move(values).

Then that temporary initializes values, but since makeWidget().data() is an rvalue (prvalue to be precise) the move-constructor is called again - with the temporary as its argument.

Now consider copy-elision:

When a nameless temporary, not bound to any references, would be moved or copied into an object of the same cv-unqualified type, the copy/move is omitted. When that temporary is constructed, it is constructed directly in the storage where it would otherwise be moved or copied to. When the nameless temporary is the argument of a return statement, this variant of copy elision is known as RVO, "return value optimization".

So the second move will (presumably) be completely elided, and only one is left - the one we would have had anyway, had the return type been the rvalue reference.

The problem with returning an rvalue reference is that if we write

auto&& values = makeWidget().data();

values will be dangling as binding an xvalue to a reference doesn't extend anythings lifetime. When we return the object type, the temporaries lifetime is extended.

这篇关于返回值或右值引用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆