执行此操作时:
int square(int& x) { return x*x;};
int s = square(40); // This gives error
要解决此问题,请执行以下操作:
int square(const int& x) { return x*x;};
int s = square(40); // This is OK
我知道40是常数但是如果我这样做会怎么样:
const int& x = 40
为什么只有const
关键字才可以?这是编译器保护的方式,没有人可以更改x
引用的值吗?
40是一个const,所以我们甚至不知道它在内存中的位置,但编译器不应该知道这个地址,因此应该允许将值从40改为30,因为编译器只能去地址&40
并将值更改为30?
答案 0 :(得分:2)
仅仅因为它可以实现并不意味着你应该这样做。 40岁真的是30岁是热闹的,但特别难以维持,不应该被允许。另外,40实际上不一定拥有地址。考虑40个高速缓存,寄存器或立即指令。
答案 1 :(得分:2)
答案 2 :(得分:2)
有关引用的规则是您不能将临时引用到非const
左值引用。文字40
可用于初始化临时,但它本身不是对象。因此,您不能将非const
左值引用绑定到它。
当你这样做时
int const& value = 40;
您实际将初始化为40
的临时对象绑定到引用value
。通常情况下,临时表格超出范围并在完整表达结束时被销毁。但是,当您直接将临时绑定到非const
引用时,其生命周期将延长以匹配引用的生命周期。
禁止将临时对象绑定到非const
引用的规则到位,主要是因为它可能会导致许多令人惊讶的结果。它可以在技术上完成,但很可能产生不明显的结果。
答案 3 :(得分:1)
你会混淆常量和文字。它们相似,但不相同。 40
不是常数,而是文字。
您不能通过引用传递文字,因为如果您通过引用传递某些内容,则意味着它可以被修改 - 文字不能。请考虑以下事项:
void foo(int &i)
{
i = 1;
}
foo(0); // What on Earth? 0 == 1?
但是,如果您传递对常量的引用,则意味着即使它是引用,也不允许该函数修改其参数(因为它是常量),所以现在你可以安全地传入一个文字 - 它现在有意义,,因为该函数不可能修改它的参数。
答案 4 :(得分:1)
你仍然可以这样做:
int x = 40;
int s = square(x)
x = 30;
s = square(x);
两个版本的square(一个或没有const)。
当您通过引用传递内容时,您传递的是现有对象(因为这就是引用意味着现有对象的别名)。
在你的例子中:
int s = square(30);
您不传递对象。这是一个文字(它们是不是对象)。编译器可以通过创建临时对象将文字转换为对象。但是语言对临时对象有明确的限制,这意味着它们是const。这意味着引用不能传递给它们将被突变的接口(尽管你可以通过const引用传递它们)。