【发布时间】:2012-04-14 15:52:07
【问题描述】:
这样的返回类型是否代表了 c++11 中有意义的东西?
template <typename R>
R&& grabStuff();
T instance = grabStuff<T>();
如果R 没有移动构造函数,我希望grabStuff 应该抛出编译时错误,因为这似乎不允许返回类型使用复制构造函数
【问题讨论】:
标签: c++ c++11 rvalue-reference
这样的返回类型是否代表了 c++11 中有意义的东西?
template <typename R>
R&& grabStuff();
T instance = grabStuff<T>();
如果R 没有移动构造函数,我希望grabStuff 应该抛出编译时错误,因为这似乎不允许返回类型使用复制构造函数
【问题讨论】:
标签: c++ c++11 rvalue-reference
与往常一样,在返回引用时,您必须返回对函数返回后仍然存在的对象的引用。你如何做到这一点取决于你。示例:
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 本身,它返回对您传递给它的东西的引用(因此调用者有责任提供有效输入)。
【讨论】:
get() 的结果分配给Foo& 的正常引用吗?
std::move本身。
Foo && rr = get();。
如果函数的返回类型是一个右值引用,那么函数调用的结果就是一个xvalue;如果返回类型是非引用,那么函数调用的结果就是prvalue。
xvalue 和 prvalue 都是右值,它们之间存在一些细微的差异,更像是引用和非引用之间的差异。例如,一个 xvalue 可能有一个不完整的类型,而一个纯右值通常应该有一个完整的类型或 void 类型。当 typeid 应用于类型为多态类类型的 xvalue 时,结果引用动态类型;而对于纯右值,结果是指静态类型。
对于你的声明语句T instance = grabStuff<T>();,如果T是类类型,我认为在这种情况下xvalue和prvalue没有区别。
初始化器是一个右值,所以编译器更喜欢移动构造器。但是如果没有声明move构造函数,并且声明了一个带有const引用参数的拷贝构造函数,那么就会选择这个拷贝构造函数,并且不会出错。我不知道你为什么希望这是一个错误。如果这是一个错误,任何旧代码在从右值复制初始化某些对象时都会不正确。
【讨论】:
它可能有意义,具体取决于您想用它做什么,以及您如何实现该功能。
实际上,std::move 返回类型是T&&(右值引用),这很有意义,因为它定义了 C++11 库中存在 std::move 的真正目的:
【讨论】:
std::move 是右值引用返回类型的唯一有意义的实例。它在用户代码中永远不会有意义。
std::move),右值引用返回类型不能做任何语义上有意义的事情。