为什么为使用临时对象访问的引用变量赋值有效,而不适用于非引用类型?
class a
{
public:
int m;
int &n;
a():m(2),n(m)
{
cout<< "A's constructor"<<endl;
}
};
int main()
{
// a().m = 6; // this gives an error that a temporary object is being used
// as an lvalue
a().n = 20; // But this line works
return 0;
}
但是a().n
真的是暂时的吗?考虑这个代码:
class a
{
public:
int m;
int &n;
a():m(2),n(m)
{
cout<< "A's constructor"<<endl;
}
a(int& _n):m(2),n(_n)
{
cout<< "A's constructor"<<endl;
}
};
int main()
{
a().n = 20; // (1)
int n = 0;
a(n).n // (2)
return 0;
}
线(2)
清楚地表明.n
不是暂时的。它不能是,因为它是对本地n
变量的引用。
但是,编译器无法知道n
将引用什么。一个人甚至可以做n(rand_bool() ? m : _n)
,它必须工作。
相反,编译使用类型系统来知道应该分配什么或不应该分配什么。
例如,文字9
是类型为int
的pr值。你不能分配给它:
9 = 8; // nope
在代码中,a()
是一个prvalue或类型a
。它的所有值成员也是。这就是a().m
不起作用的原因。m
是一个prvalue。
但是,a().n
是左值,因为n
是左值引用。无论它指向哪个变量。
a().n = 20;
由于CCD_ 15是左值引用类型,因此有效。编译器不知道n
在实现中是对m
的引用。它假定n
是一个有效的左值引用,因此接受该行。
理论上,当你分配给a().n
时,你可以分配给一个独立于a()
寿命的变量。编译器无法评估这一点,如果它不接受这一行,就会妨碍程序员。想象一下下面的用例:
// Global variable.
int gv;
class a
{
public:
int m;
int &n;
a():m(2), n(gv) // n is a reference to the global variable.
{
cout<< "A's constructor"<<endl;
}
};
int main()
{
a().n = 20; // Changes gv. It is a valid operation.
return 0;
}