xvalue的生存期限是否延长?
显然,编译器在这个问题上存在一些混淆和区别:
http://social.msdn.microsoft.com/Forums/vstudio/en-US/3c754c4e-5471-4095-afae-795c1f411612/rvalue-refs-extended-lifetime-inconsistent-with-gccstandard
根据这篇文章:
什么是右值,左值,xvalues,glvalues和prvalues?
Xvalues是rvalues(与prvalues一起),标准说:
第二个上下文是当引用绑定到临时的时候。 引用绑定到的临时对象或引用绑定到的子对象的完整对象的临时对象在引用的生命周期中保留,但以下情况除外:
但是有些帖子对此提出了异议:
右值引用是否允许悬挂引用?
什么是x值和prevalue之间的非POD对象允许的用法或行为之间的差异的示例?
有人可以澄清这个问题。 MSVC是否适合一次?
Xvalues可能是右值,但这并不意味着它们是临时值。 临时工的寿命延长来自于它们是临时性的,而不是它们的价值范畴。
我故意尝试不知道操作符处理的顺序(这样,我强迫自己编写使用明确括号或不关心顺序的代码)。 这里转载的您的特定adder
示例代码确实很在意:
template <class T>
struct addable
{
friend T operator +( const T& lhs, const T& rhs )
{
return std::move(T(lhs) += rhs);
}
friend T operator +( const T& lhs, T&& rhs )
{
return std::move(T(lhs) += std::move(rhs));
}
friend T&& operator +( T&& lhs, const T& rhs )
{
return std::move(lhs += rhs);
}
friend T&& operator +( T&& lhs, T&& rhs )
{
return std::move(lhs += std::move(rhs));
}
};
如果+
运算符从右到左完成,则t1 + t2 + t3
将运行到t1 + (t2 + t3)
。 t2 + t3
将调用第一个过载,从而产生一个临时的,从而产生t1 + temp
。 由于临时将优先绑定到r值引用,该表达式将调用第二次重载,这也会返回临时值。
但是,如果+
运算符从左到右工作,则会得到(t1 + t2) + t3
。 这给我们temp + t1
,这会导致问题。 它会称第三次超载。 该函数的lhs
参数是T&&
,对临时参考。 您返回相同的参考。 这意味着你已经返回了一个临时引用。 但是C ++并不知道; 它只知道你正在返回一个参考。
然而,这个“某事”是在最终表达式(对新变量,值类型或引用类型的赋值)进行评估之后被销毁的。 记住:C ++不知道这个函数会返回对它的第一个参数的引用。 因此无法知道传递给函数操作数的临时生命周期需要延长到存储返回参考的生命周期。
顺便说一下,这就是为什么表达树可能会对auto
和潜伏等危险。 因为创建的内部临时对象不能通过存储在各种对象中的新临时对象或引用来保存。 C ++没有办法做到这一点。
所以谁的正确取决于操作员的解决顺序。然而,我更喜欢我的解决方案:不要依赖于语言的这些角落,只是解决它们。 停止从这些重载中返回T&&
,并将该值移至临时值。 这样,它可以保证正常工作,并且不必经常检查标准以确保代码正常工作。
另外,作为旁白,我认为对于operator +实际修改其中一个参数有些粗鲁。
但是,如果你坚持知道谁是对的,那就是GCC。 从5.7节,p1:
添加剂操作符+和 - 组从左到右。
所以是的,它不应该工作。
注意:Visual Studio允许T &r2 = t1 + t2 + t3;
编译成(非常烦人的)语言扩展。 你应该希望得到它的警告。
上一篇: xvalue's lifetime bound to reference extended or not?
下一篇: Is there any danger in calling free() or delete instead of delete[]?