假设我有A级:
class A {
int i;
public:
A(){};
A(int i){this->i=i;};
};
一个简单的测试功能:
void test(const A &a){...}
现在,如果我这样做:
int main()
{
test(2);
}
它编译并调用A(int i)
构造函数。但是当我将参数更改为非const时:void test(A &a)
我收到编译错误
这些情况之间有什么区别,为什么第一个允许,第二个不允许,以及在第一个案例的初始化中实际发生了什么?
答案 0 :(得分:1)
这两种情况的区别在于允许C ++编译器创建临时对象以传递给接受const
引用的函数,但是接受非const
引用的函数必须与实际对象一起提供
当你致电test(2)
实际发生的事情是这样的:
A hidden(2);
test(hidden);
编译器创建hidden
对象,使用2
对其进行初始化,并将结果传递给test
。由于test
保证不会修改A
,因此这很好。
当test
无法提供此类保证时:设想设置新值的test
:
void test(A& a) {
a.i++; // let's pretend "i" is public
}
如果您使用实际对象(test
)致电A a(3); test(a);
,则可以在a
返回后从test
收集更新结果。另一方面,调用test(2)
无法访问更新结果。这表示逻辑中存在潜在错误,因此编译器将其视为错误。
答案 1 :(得分:0)
在第一种情况的初始化中实际发生了什么?
在第一种情况下,临时A
将由A::A(int)
隐式构造,然后绑定到对const的左值引用。 test(2);
的效果与test(A(2));
相同。
临时不能绑定到非const的左值引用,这就是第二种情况失败的原因。
答案 2 :(得分:0)
这是一个有趣的案例。使用const
,您可以绑定对rvalue的引用。下面是一个更简单的例子。
int get_num()
{
return 2;
}
int main(){
int& p = get_num(); // This is a compiler error. Can't create a non-const reference to an rvalue
const int& q = get_num(); // this will work. Can create const reference to an rvalue
}
这是c ++标准的一部分。