r 值引用返回类型语义?

Posted

技术标签:

【中文标题】r 值引用返回类型语义?【英文标题】:r-value reference return type semantics? 【发布时间】:2012-04-14 15:52:07 【问题描述】:

这样的返回类型是否代表了 c++11 中有意义的东西?

template <typename R>
R&& grabStuff();

T instance = grabStuff<T>();

如果R 没有移动构造函数,我希望grabStuff 应该抛出编译时错误,因为这似乎不允许返回类型使用复制构造函数

【问题讨论】:

【参考方案1】:

与往常一样,在返回引用时,您必须返回对函数返回后仍然存在的对象的引用。你如何做到这一点取决于你。示例:

T global_thing;

T && get()  return std::move(global_thing); 

struct Foo  Foo(T &&); /* ... */ ;

int main()

    global_thing.reset();
    Foo a(get());
    global_thing.reset();
    Foo b(get());

返回右值引用的更典型示例是std::move 本身,它返回对您传递给它的东西的引用(因此调用者有责任提供有效输入)。

【讨论】:

对象不必是全局对象。管理资源的本地对象也是一个例子(我的意思是,也许 :D)。 @Kerrek,所以你的意思是这个函数应该只在临时调用?不能将您示例中get() 的结果分配给Foo&amp; 的正常引用吗? @Nawaz:是的,正如我所说,这取决于你...我只是想举一个例子,它不是 std::move本身。 @lurscher:您也可以将结果绑定到引用:Foo &amp;&amp; rr = get();【参考方案2】:

如果函数的返回类型是一个右值引用,那么函数调用的结果就是一个xvalue;如果返回类型是非引用,那么函数调用的结果就是prvalue。

xvalue 和 prvalue 都是右值,它们之间存在一些细微的差异,更像是引用和非引用之间的差异。例如,一个 xvalue 可能有一个不完整的类型,而一个纯右值通常应该有一个完整的类型或 void 类型。当 typeid 应用于类型为多态类类型的 xvalue 时,结果引用动态类型;而对于纯右值,结果是指静态类型。

对于你的声明语句T instance = grabStuff&lt;T&gt;();,如果T是类类型,我认为在这种情况下xvalue和prvalue没有区别。

初始化器是一个右值,所以编译器更喜欢移动构造器。但是如果没有声明move构造函数,并且声明了一个带有const引用参数的拷贝构造函数,那么就会选择这个拷贝构造函数,并且不会出错。我不知道你为什么希望这是一个错误。如果这是一个错误,任何旧代码在从右值复制初始化某些对象时都会不正确。

【讨论】:

【参考方案3】:

它可能有意义,具体取决于您想用它做什么,以及您如何实现该功能。

实际上,std::move 返回类型是T&amp;&amp;(右值引用),这很有意义,因为它定义了 C++11 库中存在 std::move 的真正目的:

std::move

【讨论】:

std::move 是右值引用返回类型的唯一有意义的实例。它在用户代码中永远不会有意义。 @ildjarn:我不能声称“它永远不会在用户代码中有意义”。我只是说 rvalue-reference 作为返回类型,可能是有意义的。 我声称。 ;-] 在用户代码中(除非用户代码出于某种奇怪的原因复制std::move),右值引用返回类型不能做任何语义上有意义的事情。 @ildjarn:现在声称这种东西还为时过早; C++11 刚刚发布,在接下来的 10 年里,将会发现许多技巧和习语。所以我宁愿保持双手交叉。 您可以 A) 获得悬空引用或 B) 暗示 所有权变更而不保证所有权,这是完全没用的。就是这样。

以上是关于r 值引用返回类型语义?的主要内容,如果未能解决你的问题,请参考以下文章

请问函数的返回值类型那里,写“类名”和“类名&”有啥区别?

我的OOP学习笔记值与引用语义类型

第三章 面向对象编程 3.1类型系统

go 函数

C++11的新鲜事儿~

C++11的新鲜事儿~