当前位置: 首页 > news >正文

C++---ref-qualifier( / )函数的左右值调用的界定

1. ref-qualifier的定义

ref-qualifier 是 C++11 引入的一种成员函数限定符,用来限制成员函数只能在特定引用类型的对象上调用。它有两种形式:

  • & :只能在左值对象上调用
  • &&:只能在右值对象上调用

语法位置在函数的cv-qualifier(const/volatile)之后(如果有),函数体之前。

struct Foo {void bar() &;   // 仅左值对象可调用void bar() &&;  // 仅右值对象可调用
};

2. ref-qualifier的作用

在 C++11 之前,我们无法区分成员函数是通过左值还是右值对象调用的。例如:

struct String {const char* data() const { return ptr; }
private:const char* ptr;
};String make_string();auto p = make_string().data(); // 危险:返回的指针指向临时对象,临时对象已销毁

使用 ref-qualifier 可以避免这种情况:

struct String {const char* data() const & { return ptr; }          // 左值调用const char* data() const && = delete;               // 禁止右值调用
private:const char* ptr;
};

这样 make_string().data() 会在编译期被禁止。


3. 基本语法与重载规则

ref-qualifier 参与函数重载决议,规则如下:

  1. 左值对象优先匹配 & 限定的函数
  2. 右值对象优先匹配 && 限定的函数
  3. 如果没有匹配的 ref-qualifier,会尝试无 ref-qualifier 的函数(如果存在)
  4. const/volatile 限定符与 ref-qualifier 可以组合
struct A {void f() &  { std::cout << "lvalue\n"; }void f() && { std::cout << "rvalue\n"; }
};A a;
a.f();          // 输出 "lvalue"
std::move(a).f(); // 输出 "rvalue"
A().f();        // 输出 "rvalue"

4. 与 const/volatile 的组合

ref-qualifier 必须放在 cv-qualifier 之后:

struct B {void g() const &;   // const 左值void g() &;         // 非 const 左值void g() const &&;  // const 右值void g() &&;        // 非 const 右值
};

重载决议优先级(从高到低):

  1. 非 const 右值
  2. const 右值
  3. 非 const 左值
  4. const 左值

5. 与模板的结合

ref-qualifier 可以与模板参数结合,用于实现完美转发:

template<typename T>
struct Wrapper {T value;template<typename U>Wrapper(U&& u) : value(std::forward<U>(u)) {}// 只有当 *this 是右值时,才返回右值引用T&& get() && { return std::move(value); }// 当 *this 是左值时,返回左值引用T& get() & { return value; }
};

6. 与完美转发的关系

ref-qualifier 常用于实现成员函数的完美转发,避免不必要的拷贝:

struct Builder {std::string result;// 允许链式调用Builder& operator<<(const std::string& s) & {result += s;return *this;}// 右值版本:不返回引用,避免悬垂引用Builder operator<<(const std::string& s) && {Builder tmp = std::move(*this);tmp.result += s;return tmp;}
};

7. 与继承和虚函数

ref-qualifier 参与函数签名,因此会影响虚函数覆盖:

struct Base {virtual void foo() &;virtual void foo() &&;
};struct Derived : Base {void foo() & override;void foo() && override;
};

注意:如果基类函数有 ref-qualifier,派生类覆盖时必须使用相同的 ref-qualifier。


8. 实用场景

8.1 阻止对临时对象调用某些函数

struct File {FILE* fp;File(const char* name) { fp = fopen(name, "r"); }~File() { if (fp) fclose(fp); }// 禁止对临时文件对象调用 read()size_t read() && = delete;size_t read() & {// 读取文件内容return 0;}
};

8.2 优化返回值

struct Matrix {std::vector<double> data;// 右值版本可以直接移动内部数据std::vector<double> get_data() && {return std::move(data);}// 左值版本只能返回拷贝std::vector<double> get_data() & {return data;}
};

8.3 实现流式接口

struct Logger {std::stringstream ss;Logger& log(const std::string& msg) & {ss << msg;return *this;}std::string log(const std::string& msg) && {ss << msg;return ss.str();}
};

9. 陷阱与注意事项

  1. ref-qualifier 是函数签名的一部分

    • 这意味着 void f() &void f() 是两个不同的重载函数
  2. ref-qualifier 不能用于静态成员函数

    • 静态成员函数不属于任何对象实例,因此不能有 ref-qualifier
  3. 不要滥用 && 限定符

    • 过度使用可能导致代码可读性下降
    • 只在需要区分左值/右值行为时使用
  4. 注意 const 与 ref-qualifier 的组合

    • const&&& 是不同的限定符,会影响重载决议

睡眠等同于希望。每次醒来都是一个新的开始,一个新的希望。 —E·M·齐奥朗

http://www.dtcms.com/a/495257.html

相关文章:

  • vue3:数组的.includes方法怎么使用
  • 网站建设及网页设计企业宣传片公司
  • 132.MIG IP核中没有512M16的只有512M8的如何解决
  • SwiftUI 布局之美:Padding 让界面呼吸感拉满
  • RHCSA-08文本处理工具
  • JSP XML 数据处理
  • “String到Date转换失败”:深挖@RequestBody的日期坑
  • 分布式事务以及Seata(XA、AT模式)
  • 做网站的 简历标识设计网
  • 平台网站建设意见征求表社区类网站开发
  • 电脑零配件行业MES系统:快速实现全过程信息溯源
  • 基于单片机与上位机的智能宠物喂食管理系统设计
  • 新奇特:黑猫警长的纳米世界,忆阻器与神经网络的智慧
  • 【深度学习新浪潮】LLM 大模型压缩落地实践(2025 版)
  • 神经网络之计算图repeat节点
  • 河北廊坊做网站珠海企业网站设计
  • 网站建设培训 ppt做网站有哪些
  • 【RK3588开发】RKNN库的使用
  • 使用 Python 语言 从 0 到 1 搭建完整 Web UI自动化测试学习系列 18--测试框架Pytest基础 2--插件和参数化
  • 玩具 网站模板成立一个网站
  • 阿里网站注册阿里云网站怎么建设
  • 【排查实录】Web 页面能打开,服务器能通接口,客户端却访问失败?原因全在这!
  • 【Linux】系统性能排查:解决卡顿问题
  • 建网站要注意的细节建免费的网站
  • 手机网站建设收费网站建设 合肥
  • Qwen3-0.6模型开关思考模式测试
  • FT62FC3X 8位MCU单片机选型表,详细解析FT62FC31A/32A/33A/35A/3FA
  • 鸿蒙NEXT Sensor Service Kit开发指南:解锁传感器数据的无限潜能
  • 开源项目:FlyCut Caption智能视频字幕裁剪工具
  • Fedora 16上源码建立pydev + eclipse的OpenStack开发环境笔记草稿