2014-04-03 28 views
11

我们不能写int& ref = 40,因为我们需要lvalue在右侧。但我们可以写const int& ref = 40。为什么这可能? 40 is rvalue instead lvalue强制参考和左值

我知道这是一个例外,但为什么?

+0

绝对是一个骗局。 –

回答

10

作为Stroustrup的说:

为一个constŤ&初始化器不必是一个左值或者甚至 类型T.在这种情况下:

[1]首先,隐式类型转换到必要时应用T.

[2]然后,将所得的值被置于

[3]最后,本临时变量被用作 初始化的值 类型T的临时变量。

因此,当您键入const int& ref = 40时,临时int变量在幕后创建,并且ref被绑定到此临时变量。

11

该语言中有一条规则允许将常量左值引用绑定到右值。该规则的主要理由是,如果它不存在,那么你就必须提供的功能,不同的重载能够使用的临时对象参数:

class T; // defined somewhere 
T f(); 
void g(T const &x); 

有了这条规则,你可以做g(f()) ,如果没有它,才能够做到这一点,你需要创建一个不同的g重载需要一个右值(这是从时间,其中右值引用,甚至没有在语言!)

+0

我仍然不确定为什么[生命周期延长](http://stackoverflow.com/q/20546981/596781),虽然:-( –

+0

@KerrekSB:我想最初的原因是这样你可以写'T const&_ = ...;'或'T const _ = ...;无所谓,两者都可以工作,前者在表达产生参考时更有效率(无副本)。这是相当可惜了,虽然,因为它可以让很多的击打在 –

+1

@KerrekSB滑。我想我已经在链接的问题,解决这一点。这是允许在通用上下文中进行绑定的副作用(不仅在函数参数中),也不希望它在每次使用时都导致未定义的行为。如果没有生命周期的延伸:'T const&x = f();'后面跟*任何* odr-x的使用都是未定义的行为,引发了为什么要放在第一位的问题?因此,无论是否提供一致性(引用都绑定在任何*上下文中)和终生扩展,或者您接受不一致,并且不需要终生扩展。该语言的前者。 –

2

为什么有可能吗?

40是这里的文字。常量引用可以用文字和临时对象来初始化,以延长它们的使用寿命。

int const& ans = 40; 
// transformed: 
int __internal_unique_name = 40; 
int const& ans = __internal_unique_name; 

另一种情况是,当你有一个功能,例如:这可以通过编译器来完成这样

void f(std::string const& s); 

,你想用

f("something"); 

这叫它临时变量只能绑定到const引用。

+1

这也是与非const引用的情况下... –

+0

@DavidRodríguez-dribeas不是第二种情况提供 – 4pie0

+0

这正是编译器会为你做,它调用映射到:'的std :: string __tmp(”东西“); F(__ TMP);'。这是*,因为你可以*不是为'const'引用(* alone *)允许这么做的原因,事实证明,Solaris CC和VS通过完全相同的方式支持对临时对象的非const引用的绑定事情。 –

1

您可以将右值绑定到const引用。该语言保证绑定对象的存在直到引用的范围结束,甚至静态调用正确的析构函数。这是例如在ScopeGuard实现(http://www.drdobbs.com/cpp/generic-change-the-way-you-write-excepti/184403758?pgno=2)中使用,使其具有类似虚拟析构器的行为,而无需支付虚拟方法调用。

+0

编译器没有选择万年此事。语言规则决定了生活时间。 –