0

我正在通过引用返回并遇到临时对象。我不明白如何识别它们。请使用此示例进行说明:

如果ab是同一类的对象,请考虑 binary operator+。如果您在表达式中使用它f(a+b),则 , thena+b将成为临时对象并且f必须以f(const <class name>&)or的形式出现f(<class name>)。它不能是形式f(<class name>&)但是,(a+b).g()在哪里g()甚至可以更改由a+b.

4

3 回答 3

4

当您说f(a + b)时,参数f需要绑定到调用函数的值,并且由于该值是右值(具有非引用返回类型的函数调用的值)*,因此参数类型必须是const-lvalue-reference、右值引用或非引用。

相比之下,当你说 时(a + b).g(),临时对象被用作成员函数调用中的隐式实例参数,它不关心值类别。可变值绑定到非 const 和 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

*) 这适用于本例中的重载运算符,也适用于内置二元运算符。您当然可以制作产生左值的重载运算符,尽管违反常见约定可能会被认为非常混乱。

于 2013-10-18T18:41:00.523 回答
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 需要两个整数,所以程序必须计算 and 的值a * c并将b * c它们存储在某个地方——它不能将它们存储在aorbc中。所以生成的代码等价于:

int lhsParam = a * c;
int rhsParam = b * c;
return func(lhsParam, rhsParam);

同样,在最后func()我们返回一个计算值,lhs + rhs。编译器必须将它存储在一个新的地方。

对于整数等,这似乎很简单,但请考虑

int function(std::string filename);
function("hello");

filename必须是 a std::string,但你通过了 a const char*。所以编译器所做的是:

std::string filenameParam = "hello"; // construct a new object
function(filenameParam);

就像前面的例子一样,但这次希望更清楚的是我们正在构建一个临时对象。

注意:称它们为“somethingParam”的约定只是为了在这个答案中清晰。

于 2013-10-18T18:49:04.780 回答
1

您的困惑不是因为您无法识别临时对象,在这两种情况下a+b都是临时对象,而是错误假设非 const 方法需要左值并且不接受临时对象,这是不正确的。

于 2013-10-18T18:46:32.063 回答