C++ 为什么这会导致C2102:'&';需要l值
我想知道,为什么下面的代码方式(已经注释掉)会导致C++ 为什么这会导致C2102:'&';需要l值,c++,C++,我想知道,为什么下面的代码方式(已经注释掉)会导致 C2102:“&”需要l值 有没有更好的方法避免使用tmp变量 class a { private: int *dummy; public: int* get_dummy() const { return dummy; } }; int main() { a aa; // error C2102: '&' requires l-value //int** me = &a
C2102:“&”需要l值
有没有更好的方法避免使用tmp
变量
class a {
private:
int *dummy;
public:
int* get_dummy() const {
return dummy;
}
};
int main()
{
a aa;
// error C2102: '&' requires l-value
//int** me = &(aa.get_dummy());
// OK!
int *tmp = aa.get_dummy();
int** me = &(tmp);
}
没有
否则,me
会包含什么地址?这里您给了它tmp
——但是如果您将它替换为int**me=&aa.get_dummy()代码>,它指向哪里
这个问题没有有意义的答案,因此标准要求&
的参数为左值。您可以定义:
int **get_dummy() ... return &dummy;
从本质上讲,可以将r值视为表达式,而l值是实际对象。表达式没有地址,即使有,也很难想象地址会有多好。很容易理解对象的地址是如何有用的
抽象地理解这样一个问题有点困难。理解指针和编译语言的最好方法是学习汇编语言。必须对左值应用&
运算符。当调用aa.get_dummy()
未分配给变量时,其返回值仅放在堆栈上,因此获取堆栈项的地址是愚蠢的(也是错误的)。因为a::get_dummy()
返回一个未命名的临时对象(int指针)
函数返回的对象<强> >栈帧,它的地址毫无意义,因为表达式结束后可能是强>无效。< /强> < /p> < p>编译器是正确的,按照ISOC++:
一元运算符&的结果是指向其操作数的指针。这个
操作数应为左值或限定id
换句话说,你可以把任何有名字的东西的地址记下来
按值从函数返回的值没有名称,通常通过寄存器返回。因此,没有“地址”可言,因为值不在内存中
有人可能会争辩说,编译器可以更智能,检测到这一点,并在使用地址的表达式期间将值存储在堆栈上。但这很容易出错(您可以“泄漏”指向表达式外部的指针),并且显然是标准的扩展(即不保证兼容)。所以MSVC干脆禁止它
有趣的是,编译器在引用右值时。但是对于指向右值的指针没有这样的功能
回答你的问题:尽量减少获取物品地址;获取变量的地址可防止优化器将其放入寄存器。
但如果必须,请返回一个引用:
class a {
private:
int dummy;
public:
int get_dummy() const {
return dummy;
}
int& get_dummy() {
return dummy;
}
};
int main()
{
a aa;
int* me = &(aa.get_dummy());
}
请注意,严格来说,不需要一个常量get_dummy()
,但它会在右值上下文中帮助优化器。它会指向哪里?
-它不是指向虚拟实例的地址吗?@Yan:否。该函数返回dummy
存储的地址(或值),不是dummy
本身。@Yan:您可以通过引用返回dummy,例如int*&get\u dummy.Hmm,您可能可以使用&aa
,但是,否则,为什么要使用间接指针?是否没有API来更改指针?你想改变它吗?获取局部变量的地址是危险的……无论是全局变量、成员变量还是局部变量,只要其生存期超过引用,指针悬空的“危险”就不存在。@YeenFei,当然,但返回局部变量的地址在任何语言中都是一种奇特的操作。当人们不完全理解运行时的现实时,保持更明显的安全可能是一个好主意。与Luca的答案相同tmp
是一个堆栈对象dummy
不是临时对象或本地对象。@Naveen:是的,这是真的。但答案并不是说“未命名的临时对象”(在其完整表达式结束前有效),而是说“堆栈对象”,这通常意味着“自动”存储中的对象在其作用域结束前有效。@Billy,在我的答案中添加了“未命名的对象”。但我在我的回复中并没有看到你们所指的“堆栈对象”。@YeenFei:stack对象由“堆栈框架顶部”和“超出范围”表示<代码>tmp
超出范围时也无效。未命名的编译器临时变量与作用域完全无关。它们一直生存到其所拥有的完整表达式的结尾。返回指针的引用。的可能重复