void swap(int& a, int& b) {}
void copy(int& a, const int& b) {}
int main() {
int a=1;
unsigned b=2;
swap(a, b);
copy(a, b);
}
C ++语言,g ++编译器。
请告诉我为什么 copy -function调用中没有编译错误,但在 swap 中 -function触发器invalid initialization of reference of type ‘int&’ from expression of type ‘unsigned int’
。
抱歉我的英语不好。
答案 0 :(得分:4)
首先 - 将U
类型的表达式与资格cv2
的参考绑定引用到具有限定条件T
的类型cv1
的引用的规则L。:< / p>
的表达式初始化
cv1 T
的引用可以通过类型cv2 U
如果
如果引用是左值引用和初始化表达式
- 是左值,
cv1 T
与参考兼容与cv2 U
或- 有一个班级类型[...]。
否则,
cv1
应为const
,或者引用应为右值参考。cv1 T
与cv2 U
的类型相同(或{{1}的基数},则
T
与参考兼容至U
如果U
等于cv1
(或更高)。
不幸(或幸运的是!!;))具有非常量左值参考参数的函数不能使用非参考兼容类型的左值调用(或者在没有可靠转换的类类型的情况下调用参考兼容类型的参数。)
让我们考虑一个带整数引用的函数和一个具有常量整数引用参数的函数。
cv2
让我们看看单个有符号值和另一个无符号值:
void doSomething (int & x)
{
// do some READ & WRITE stuff with x
x = x+5;
}
int doSomethingElse (int const & x)
{
// do some READ ONLY stuffwith x
return 3*x;
}
现在我们将名为 int a = 1;
unsigned int b = 2;
的{{1}}传递给int
:
a
这里没有魔法,引用doSomething()
绑定到 // works since x of doSomething can bind to a
doSomething(a);
// let's try to expand/"inline" what is happening
{
int & x = a;
x = 5;
}
并设置为5(因此也是a)。细
现在我们尝试将x
传递给同一个函数。但是......
a
我们开始遇到问题,并且b
调用 // ... it doesn't work/compile since
// unsigned int is not reference compatible to int
doSomething(b); // compile error here
// what's going on here
{
int & x = b; // unsigned value cannot bind to a non-const lvalue reference!
// compile error here
x = 5;
}
将无法编译。
现在让我们看看const引用函数。通过doSomething
显然不会再出现问题。 const int引用绑定到b
值。
a
好吧好吧。 int
将为int c = doSomethingElse(a);
// let's do some naive inlining again
int c;
{
int const & x = a;
c = 3*x;
}
。
如果我们将c
传递给该函数会发生什么?标准说,在这种情况下,使用复制初始化规则从初始化表达式创建并初始化类型3*a
的临时表。
b
答案 1 :(得分:0)
对于交换第二个param想要int&amp;并传递未签名的b。它并不像int&amp;没有任何帮助。
复制需要const int&amp;,允许使用临时的。你传递它unsigned,可以隐式转换为int,并且int临时可以传递给copy。
最大的区别在于第二种情况不会修改第二种情况,因此它可以在引擎盖下更换。如果交换案例允许临时,你将与临时交换,并保持b不变,这几乎不是任何人想要的。