You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何调用成员的右值方法?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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 01:55:07