2

当你这样做时:

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 是一个常量,所以我们甚至不知道它在内存中的位置,但编译器不应该知道这个地址,因此例如应该允许将值从 40 更改为 30,因为编译器可以直接转到地址&40并更改价值30?

4

5 回答 5

2

仅仅因为它可以实现并不意味着你应该这样做。40 真的是 30 很有趣,但特别难以维护,不应该被允许。此外,40 不一定地址。考虑高速缓存、寄存器或立即指令中的 40。

于 2012-11-11T14:44:37.750 回答
2

的声明square

 int square(int& x);

接受一个左值,而调用square(40)接受一个右值,这是不一致的,请在此处查看更多的左值和右值。

于 2012-11-11T14:47:18.173 回答
2

关于引用的规则是您不能将临时引用绑定到非const左值引用。文字40可用于初始化临时对象,但它本身不是对象。因此,您不能将非const左值引用绑定到它。

当你这样做

int const& value = 40;

40您实际上绑定了一个初始化为引用的临时对象value。通常,临时对象超出范围并在完整表达式结束时被销毁。但是,当您直接将临时绑定到非const引用时,它的生命周期会延长以匹配引用的生命周期。

禁止将临时对象绑定到非const引用的规则已经到位,主要是因为它可能会导致许多令人惊讶的结果。它在技术上可以完成,但很可能会产生不明显的结果。

于 2012-11-11T14:49:26.193 回答
1

你仍然可以这样做:

int x = 40;
int s = square(x)

x = 30;
s = square(x);

使用两个版本的 square(一个或没有 const)。

当您通过引用传递某些东西时,您正在传递一个现有对象(因为这就是引用意味着现有对象的别名)。

在您的示例中:

int s = square(30);

没有传递一个对象。这是一个文字(它们不是对象)。编译器可以通过创建临时对象将文字转换为对象。但是该语言对临时对象有明确的限制,这意味着它们是 const。这意味着不能将引用传递给它们将被改变的接口(尽管您可以通过 const 引用传递它们)。

于 2012-11-11T14:55:46.993 回答
1

你混淆了常量和文字。它们相似,但不等价。40不是常数,而是字面量。

您不能通过引用传递文字,因为如果您通过引用传递某些内容,则意味着它可以被修改 - 文字不能。考虑以下:

void foo(int &i)
{
    i = 1;
}

foo(0); // What on Earth? 0 == 1?

但是,如果您传递对常量的引用,则意味着即使它是引用,也不允许该函数修改其参数(因为它是常量),所以现在您可以安全地传入一个字面量 - 它现在使感觉,因为函数不可能修改其参数。

于 2012-11-11T14:41:41.677 回答