可以经常读到,您无法将正常的左值引用绑定到临时对象。因为那个人可以经常看到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)。我是对的吗?
答案 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 ++编译器允许执行与您的对象类似的操作,但这不是标准的。