有人可以向我解释为什么这两个陈述有区别吗?
class A{};
const A& a = A(); // correct
A& b = A(); // wrong
它说
从类型为A&
A
类型的非const引用
为什么const
在这里很重要?
答案 0 :(得分:14)
必须使用l值初始化非const引用。如果你可以用临时工具初始化它们,那么下面会做什么?
int& foo = 5;
foo = 6; // ?!
const
引用具有特殊属性,它们延长了裁判的生命,并且由于它们是const
,因此您不可能尝试修改不存在的内容记忆。例如:
const int& foo = 5;
foo = 6; // not allowed, because foo is const.
请记住,引用实际上必须引用某些东西,而不仅仅是临时变量。例如,以下内容有效:
int foo = 5;
int& bar = foo;
bar = 6;
assert(foo == 6);
答案 1 :(得分:3)
这方面的术语有点令人困惑;你可能想进一步研究它们。这是简短的答案:
您正在为变量分配一个临时对象(调用类的构造函数的结果)。临时对象是R值。您不能将R值分配给非const引用。
你可以为一个const引用分配一个R值,虽然允许它的理由非常模糊。
答案 2 :(得分:1)
对于临时/右值,您只能有一个const引用。
您可以对非临时/左值进行非const引用。
A a;
A& b = a;
我认为其原因是为了强化左值是暂时的这一事实,因为能够修改即将消失的东西几乎没有价值。
答案 3 :(得分:1)
在C ++语言中,将非const引用附加到rvalue是非法的,而将const引用附加到rvalue是完全可以的。例如,这是合法的
const int& r = 5;
虽然这不是
int &r = 5; // ERROR
表达式A
返回的A()
类型的临时对象是右值,因此上述规则也适用于您的情况。
答案 4 :(得分:0)
因为标准是这样说的:
§8.5.3.5...否则,引用应该是对非易失性const类型的左值引用...
但是,如果你非常想要它,你可以得到它:
#include <iostream>
int main()
{
const int & cr=5;
int & r=const_cast<int &>(cr);
r=6;
std::cout<<r;
}
// outputs 6 with c++/clang++, Debian 8, amd64
但请注意,假设的常量cr不再是const,并且您会产生未定义的行为。 (§1.9(4))
如上述代码所示,差异没有技术原因。更确切地说,设计师们曾经做过噩梦,关于用户对非临时引用临时用户会做些什么。