C++派生类访问成员报using temporary as lvalue错误原因及修复
问题复现代码
#include<iostream> class acc{ public: acc() { aa = 10;} int aa; }; class Derv; class Base{ public: Base() {} int a; virtual acc get_acc() {}; virtual void compare(Derv *v) {} }; class Derv : public Base { public: acc acc_o; Derv() {} virtual acc get_acc(); virtual void compare(Derv *v) { if(v->get_acc().aa = acc_o.aa) { std::cout<<"Values Match\n"; } } }; acc Derv::get_acc() { return acc_o; } int main() { Base *d1 = new Derv(); Base *v = new Derv(); Derv *v1 = dynamic_cast<Derv *>(v); d1->compare(v1); std::cout<<d1->get_acc().aa<<std::endl; return 0; }
GCC编译报错
accessor_test.cpp: In member function ‘virtual void Derv::compare(Derv*)’: accessor_test.cpp:25:40: error: using temporary as lvalue [-fpermissive] if(v->get_acc().aa = acc_o.aa) {
错误触发逻辑
get_acc()方法的返回值类型为acc,属于按值返回。调用该方法时,程序会拷贝内部存储的acc实例,生成一个生命周期仅覆盖当前表达式的临时对象,该临时对象属于右值,表达式执行结束后会立刻销毁。- 报错行中使用了单等号
=(赋值运算符),而非做相等判断的双等号==,代码实际逻辑是尝试将acc_o.aa的值写入临时acc对象的aa成员,再判断赋值结果是否为真。 - C++语法禁止将临时右值作为可修改的左值使用,因此直接触发编译错误。即使通过
-fpermissive编译选项强制跳过该错误,赋值操作修改的是即将销毁的临时对象,既不会改动原实例的成员值,也完全不符合值比较的预期逻辑,属于无效操作。
补充说明:C++允许读取临时对象的成员值,如果此处使用==仅读取临时对象的aa字段做比较,不会触发该编译错误。
修复方案
- 方案1(匹配原代码的值比较需求,最小修改):将条件判断中的赋值符
=替换为相等比较符==,修改后仅读取临时对象的成员值做判断,符合语法规则,可正常编译运行。
修正后的compare方法代码:virtual void compare(Derv *v) { if(v->get_acc().aa == acc_o.aa) { std::cout<<"Values Match\n"; } } - 方案2(适配需要修改返回对象的场景):如果后续需要通过
get_acc()直接修改内部存储的acc实例,可将该方法的返回值类型改为左值引用acc&,此时方法返回的是内部成员本身,不会生成临时副本,可以作为合法左值被赋值。需要注意基类的虚函数声明必须同步修改返回值类型,否则虚函数重写会失效。
基类虚函数修改示例:
派生类对应修改:// 可根据业务逻辑调整为纯虚函数或补充合法返回值 virtual acc& get_acc() {};// 类内声明 virtual acc& get_acc(); // 类外实现 acc& Derv::get_acc() { return acc_o; }
内容的提问来源于stack exchange,提问作者Bhaskar
相关产品推荐
相关产品推荐

