如何调用成员的右值方法?C++编译报错问题问询
右值限定成员函数封装时的编译错误分析与解决
问题代码
class Impl { public: /// Called from Dtor. /// You can't reuse this after it has been closed /// Therefore && added so need temporary / rvalue ref. void Close(int why) && noexcept { /*...*/ } }; class Interface { public: void Close(int why) && noexcept { _i.Close(why); } private: Impl _i; };
编译报错
Lintian报错
error: 'this' argument to member function 'Close' is an lvalue, but function has rvalue ref-qualifier
g++报错
main.cpp: In member function ‘void Interface::Close(int) &&’: main.cpp:15:51: error: passing ‘Impl’ as ‘this’ argument discards qualifiers [-fpermissive] 15 | void Close(int why) && noexcept { _i.Close(why); } | ^ main.cpp:4:10: note: in call to ‘void Impl::Close(int) &&’ 7 | void Close(int why) && noexcept { } |
错误原因分析
核心矛盾在于成员变量的左值属性与右值限定函数的要求不匹配:
- Interface::Close被
&&限定,说明只有当Interface对象是右值(临时对象或经std::move转换的对象)时才能调用该函数。 - 但在Interface::Close内部,成员变量
_i是一个左值——它属于当前Interface对象,有确定的内存地址和名称,并非临时对象。 - Impl::Close要求调用它的对象必须是右值(同样被
&&限定),直接用_i.Close(why)相当于把左值的_i作为this指针传入,违反了函数的限定规则,因此编译器报错。
解决方法
通过std::move将左值的_i转换为右值引用,匹配Impl::Close的右值限定要求:
修改Interface的Close函数:
#include <utility> // 需要包含std::move的头文件 class Interface { public: void Close(int why) && noexcept { std::move(_i).Close(why); } private: Impl _i; };
这里std::move(_i)仅做类型转换,不会立即移动对象内容,只是告诉编译器把_i当作右值处理,从而满足Impl::Close对this指针的右值要求。
设计思路补充
你的设计意图(限制Close只能在即将销毁的右值对象上调用,避免后续复用)是合理的,但需要注意:即使外部对象是右值,其内部成员变量默认仍为左值,必须显式转换才能匹配右值限定的成员函数。
内容的提问来源于stack exchange,提问作者Stewart
相关产品推荐
相关产品推荐

