我正在通过引用返回并遇到临时对象。我不明白如何识别它们。请使用此示例解释:
如果a
和b
是同一类的对象,请考虑二进制operator+
。如果您在f(a+b)
这样的表达式中使用它,那么a+b
将成为临时对象,而f
必须形成f(const <class name>&)
或f(<class name>)
。它不能是f(<class name>&)
格式但是,(a+b).g()
完全没问题,g()
甚至可以更改a+b
返回的对象内容。
答案 0 :(得分:4)
当你说f(a + b)
时,f
的参数需要绑定到调用函数的值,因为该值是一个rvalue(是非函数调用的值) -reference return type)*,参数类型必须是const-lvalue-reference,rvalue-reference或non-reference。
通过约束,当你说(a + b).g()
时,临时对象被用作成员函数调用中的隐式实例参数,它不关心值类别。可变值绑定到非const和const成员函数,而const值只绑定到const成员函数(类似于volatile
)。
实际上,C ++ 11 确实添加了一种方法来限定隐式实例参数的值类别,如下所示:
struct Foo()
{
Foo operator+(Foo const & lhs, Foo const & rhs);
void g() &; // #1, instance must be an lvalue
void g() &&; // #2, instance must be an rvalue
}
Foo a, b;
a.g(); // calls #1
b.g(); // calls #1
(a + b).g(); // calls #2
*)这是本例中重载运算符的情况,也是内置二元运算符的情况。当然,您可以创建生成左值的重载运算符,但是违反常见约定可能会被认为非常混乱。
答案 1 :(得分:1)
你的困惑并非源于你无法识别临时对象,在这两种情况下a+b
的结果都是临时对象,但错误的假设是非const方法需要左值并且不接受临时对象,这是不正确的。
答案 2 :(得分:1)
对于一个简单的案例,请考虑以下代码:
int func(int lhs, int rhs)
{
return lhs + rhs;
}
int main() {
int a = 1, b = 2, c = 3;
return func(a * c, b * c);
}
因为func采用两个整数,程序必须计算a * c
和b * c
的值并将它们存储在某处 - 它不能将它们存储在a
或{{ 1}}或b
。因此得到的代码相当于:
c
同样,在int lhsParam = a * c;
int rhsParam = b * c;
return func(lhsParam, rhsParam);
的末尾,我们返回一个计算值func()
。编译器必须将它存储在新的位置。
对于整数等等,这似乎很简单,但请考虑
lhs + rhs
int function(std::string filename);
function("hello");
必须是filename
,但您通过了std::string
。那么编译器的作用是:
const char*
就像前面的例子一样,但是这次我们希望更清楚地构建一个临时对象。
注意:调用它们的惯例&#34; somethingParam&#34;这个答案只是为了清楚。