什么是临时对象和引用的处理?

时间:2011-05-05 09:47:06

标签: c++ reference lvalue

可以经常读到,您无法将正常的左值引用绑定到临时对象。因为那个人可以经常看到A级方法采用const A&作为参数,当他们不想涉及复制时。然而,这种结构是完全合法的:

double& d = 3 + 4;

因为它没有将临时对象3 + 4绑定到引用d,而是使用对象3 + 4初始化引用。正如标准所说,只有当值不是类型或引用(或继承)时,引用才会赢不能使用从临时对象使用转换或sth(即另一个临时对象)获得的对象进行初始化。在这种情况下你可以看到:

int i = 2;
double & d = i;

这不合法,因为我不是双重类型,也不是它的继承。然而,这意味着,临时工可以绑定到引用 - 但它是否真的具有约束力?是不是使用临时对象作为参数的复制构造函数创建新对象?

因此,正如我认为的那样,采用const A& amp; param而不是A&不是在第二种情况下,这样的方法将不能作为参数临时对象的类型A(因为它会),但因为它涉及复制构造函数(就像参数将是类型A)。我是对的吗?

5 个答案:

答案 0 :(得分:7)

首先,正如其他人所说,     双&安培; d = 3 + 4; 是合法的C ++;如果您的编译器接受它,并声称 正在编译C ++,这在编译器中是一个错误。 (注意 除非你给出,否则大多数C ++编译器都不会声称编译C ++ 它们是特殊选项,在g ++的情况下为-std=c++98,用于 例子。)

其次,这条规则的动机来自经验。 请考虑以下示例:

void
incr( int& i )
{
    ++ i;
}

unsigned x = 2;
incr( x );  //  Implicit conversion of unsigned to int
            //  creates a temporary.
std::cout << x << std::endl;
            //  and x is still equal 2 here.

引用的原始实现没有这个 限制;你可以使用a初始化任何引用 临时。实际经验表明这很容易出错, 因此需要引用const的限制是 介绍。 (大约在1988年或1989年,所以今天没有任何借口 让编译器不强制执行它。)

另请注意,人们经常会听到将临时绑定到a const引用延长了临时的生命周期。这是非常的 误导性:使用临时初始化引用扩展 临时的生命(有一些例外),但是 如果使用此引用进行初始化,则不会延长生命周期 其他引用,即使临时也是必然的 那些参考文献。

答案 1 :(得分:6)

如果您担心函数参数列表中const &&的含义和目的,我担心您正在咆哮错误的树,因为它与临时对象几乎没有关系。 / p>

void method( Object x );

这会从实际参数中复制构造Object。当函数终止时,对函数内的x所做的任何更改都将丢失,函数的参数不会更改。

但你不想支付复制费用。

void method( Object & x );

从实际参数中复制构造Object,但x 引用到参数,即对{{1}进行的任何更改函数内部实际上是对参数本身进行的。

但是你不希望让方法的调用者想知道他们的论点会发生什么。

x

从实际参数中复制构造void method( const Object & x ); Object无法在函数中更改。

您不需要为复制构造函数付费,并且您向调用者明确说明他的参数不会被篡改。

你不能将临时对象作为参数传递给第二个变体(参见unapersson的答案),因为没有可变对象可以引用,但是因为该函数大声预示它将修改参数(因为它被声明为非const引用),传递一个临时的参数是无意义的。

答案 2 :(得分:1)

double& d = 3 + 4; 完全合法,实际上它不会被符合标准的编译器所接受。 3+4的结果是int类型的临时结果 - 因此它只能绑定到const引用。

绑定引用真的具有约束力。没有涉及复制。它只是延长临时对象的生命周期。

答案 3 :(得分:0)

void f( int & n ) {
}

int main() {
    f( 1 + 2 );
}

不涉及复制构造,但临时不受约束。 g ++出错是:

  

非const的初始化无效   'int&amp;'类型的引用从一个   'int'类型的右值

答案 4 :(得分:0)

引用可以通过相同类型的左值初始化,而3 + 4不是左值。所以这不合法。 MS VC ++编译器允许执行与您的对象类似的操作,但这不是标准的。