C++11 是否可以/合法地返回对通过引用传递的输入临时参数的引用

C++11 是否可以/合法地返回对通过引用传递的输入临时参数的引用,c++11,object-lifetime,C++11,Object Lifetime,我的问题是:返回对通过引用传递的输入变量的引用是否合法。 我借用和的例子 一般性问题是(摘自) 这是否可能: 改变 A compute(A&& v) { (do something to v) return v; } 到 是的,函数返回对输入参数的引用是合法的,从这个意义上说,它将进行编译,并且在很多情况下它都可以正常工作。在表达式中创建的任何临时变量的生存期都是完整表达式或语句的生存期,因此,只要引用没有超出表达式的范围,使用就应该正常。不过,这有点风险,因为调用

我的问题是:返回对通过引用传递的输入变量的引用是否合法。 我借用和的例子

一般性问题是(摘自)

这是否可能:

改变

A compute(A&& v)
{
  (do something to v) 

  return v;
}


是的,函数返回对输入参数的引用是合法的,从这个意义上说,它将进行编译,并且在很多情况下它都可以正常工作。在表达式中创建的任何临时变量的生存期都是完整表达式或语句的生存期,因此,只要引用没有超出表达式的范围,使用就应该正常。不过,这有点风险,因为调用方可能不知道函数所做的引用传播,并且当引用通过中间函数传递时,临时生存期扩展的特殊规则通常不适用

您的示例涉及修改和返回对非
const
lvalue实例的引用。通常,这些类型的使用比引用
const
或引用右值更难陷入陷阱。对non-
const
lvalue的引用不能绑定到一个临时变量(至少在不经过一些圈套欺骗编译器的情况下是这样),因此您通常必须将一个实际的l值(非临时)命名变量(或其他长寿命对象)传递给它们。当该引用作为返回值从函数中传递出去时,它将引用传入的任何长寿对象。(当然,如果您没有正确管理生命周期,您仍然会遇到麻烦,但至少我们在本例中讨论的生命周期通常不止一个语句/表达式。)


如果通过函数传递右值引用,特别是如果它们被转换为表达式树下某个位置的非常量左值(这有点容易,因为作为一种安全特性,该语言会在右值与名称绑定时将其衰减为左值),引用的临时性可能会丢失,并且更容易意外地将引用绑定到一个长期引用,该引用将比它绑定到的临时引用(通常不会超过创建它的语句/完整表达式)更有效)。这就是为什么我通常喜欢按值返回(通常传递)r值,而不是按引用。然后,编译器会更清楚地意识到生命周期问题,并且使用方法通常更简单。在许多情况下,编译器无论如何都可以省略move构造,如果不能,则move通常比较便宜。

我知道这只是一个示例,但您是否尝试过编译和运行该代码?除了一些语法错误外,它从不复制任何对象,也从不创建任何临时变量。这是
运算符*
的一个相当奇怪的用法,因为实际上实现了
运算符*=
。只需正确定义
运算符*
(即返回对象,而不是引用)。谢谢stefan。运算符*只是一个例子来说明我的问题:返回对传递的输入变量的引用合法吗reference@liangbright:是的,这就是您实际实现
操作符*=
operator@stefan谢谢我更新了示例并在vs2013中进行了测试。尽管临时对象是通过引用传递的,但它给出了正确的答案。在我的RealMatrix类中,我确实需要创建一些临时对象。我可以通过值从函数返回它们(使用std::move),并通过引用将它们传递给函数。但如果我通过引用传递并返回它们,则不会复制任何对象->节省时间。我在vs2013上测试了我的课程,很好。但我不知道它是c++11标准,还是只有vs2013支持它。谢谢。我猜您的建议是在main()中,{T aaa;通过引用FuncA(aaa)将aaa传递给函数:T&FuncA(T&),并从FuncA}返回引用(T&)是合法的。但是,将T FuncB()作为FuncA(FuncB())向FuncA传递一个类型为T的临时对象(未命名),这是不好的。解决方案是将T&FuncA(T&)更改为T&FuncA(T&&)或T FuncA(T&&)。这就是你的建议吗?你的例子行不通
FuncB()
返回一个右值,该右值不能绑定到非
const
左值引用。(试一试——你会得到一个编译错误。)如果
FuncA
改为:
T const&FuncA(T const&T){return T;}
,那么是的,你会有问题
FuncA(FuncB())
将返回对临时语句的引用,该临时语句的生存期在当前语句结束时结束,因此,如果您尝试保存并使用该语句之外的引用,您将点击UB。解决方案取决于您试图做什么,但是
T&&FuncA(T&&)
通常不会这样做;这些“技巧”包括MSVC编译器的默认设置:允许它的语言扩展。不幸的是,T FuncA(T&&A){modify A,比如A=A+1;return std::move(A)}是一个解决方案吗?那么我可以用FuncA(FuncB)?这是从@dyp借用的,谢谢。但是我确实需要使用FuncA(FuncB()),而不使用auto A=FuncB();FuncA(A);有解决办法吗?
    (A+B*C)*((A*B + C)*A)
A compute(A&& v)
{
  (do something to v) 

  return v;
}
A& compute(A& v)
{
  (do something to v) 
  return v;
}