为什么不能为非const引用赋值?

时间:2016-02-13 15:29:42

标签: c++

为什么这些定义都可以:

int func(int p=255) {
    return p;
}


int func1(const int &p=255) {
    return p;
}

但是这个定义:

int func2(int &p=255) {
    return p;
}

导致编译错误?

它背后的逻辑是什么?

4 个答案:

答案 0 :(得分:3)

通过引用方式获取参数,您不使用变量的本地副本,但使用已在调用函数范围内定义的变量。

虽然你的第一个例子是有意义的(你有一个可以填充默认值的局部变量p),但第二个例子有点棘手:通常在使用引用时你希望变量有一个地址,因为你想要修改它。对于const-refernces,编译器仍然允许你传递一个文字,即使像“引用文字”这样的东西根本没有意义。

在第三种情况下,编译器希望您修改p。但这种修改应该影响哪一部分记忆? “255”没有地址 - 因此它不能用作参考。

如果您想要更详细的解释,您应该寻找“rvalue”和“lvalue”等关键字。

答案 1 :(得分:2)

非const引用必须绑定到左值(即可以获取其地址)。 255(即int literal)不是左值,因此int &p=255失败。

const引用可以绑定到rvalue,对于这种情况,将创建一个临时int并从255初始化。临时int的生命周期与const引用相同。

答案 2 :(得分:0)

尝试的功能定义

auto func2( int& p = 255 )
    -> int
{ return p; }

...失败,因为您无法将rvalue绑定到对非const的引用。基本上,该规则是因为像255这样的简单值不可修改。虽然引用可用于修改。

一个简单的解决方案是将默认值表示为单独的重载:

auto func2( int& p )
    -> int
{ return p; }

auto func2()
    -> int
{
    int scratchpad = 255;
    return func2( scratchpad );
}

答案 3 :(得分:0)

int func(int p=255) {
    return p;
}

p此处按值复制,并且定义为存在于func的范围内。

int func2(int &p) {
    return p;
}
// e.g. use:
int value = 10;
func2(value);  // func2 *could* modify value because it is passed by non-const reference

在这种情况下,编译器在此期望p在内存中的某个位置(即左值),因此它可以在func2内写入它。通过非const引用传递允许您修改函数调用中使用的变量。由于p必须属于其他人,因为它可以修改,因此您无法为其指定默认值。

但是const参考案例怎么样?在这里,编译器足够聪明,知道p永远不会被写入,因为它是const,因此它不需要在内存中有一个名称来写入。在传递文字的情况下(例如255),它(在幕后)基本上创建一个临时变量并将该临时变量传递给函数。

int func1(const int &p=255) {
    return p;
}

func1(10);

// Behind the scenes, the compiler creates something along these lines
// since it can never be modified.
const int some_temporary = 10;
func1(some_temporary);