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

RVO优化

1. 名词与结论

  • RVO(Return Value Optimization):返回临时对象时,编译器省掉临时对象与目标对象之间的拷贝/移动构造。
  • NRVO(Named RVO):返回具名局部对象时的优化(return obj;)。
  • C++17 起的“强制性拷贝省略”:在某些情形下(见 §2),标准保证不产生临时与拷贝/移动;不是“可选优化”,而是语义的一部分。

2. 何时一定省掉拷贝(C++17 保证)

以下情形创建的是目标对象本体,不会先构造临时再搬运:

  1. 直接返回临时

    T make() { return T(args); }  // 保证无拷贝/无移动
    
  2. 返回花括号临时

    struct S { int a; double b; };
    S make() { return {1, 2.0}; } // 同样保证
    
  3. 用函数返回值初始化对象(同类型)

    T x = make();  // prvalue 直接用于构造 x,无中间临时
    

启示:尽量返回临时或简单构造式;C++17 起无需为“省一次移动”做多余技巧。

3. NRVO(具名变量)什么时候能触发

NRVO 不是强制,但主流编译器(GCC/Clang/MSVC)几乎总能触发,条件包括:

  • 返回的对象是同一作用域的非 volatile 局部自动对象
  • 返回语句在所有路径上都返回同一个对象(越一致越容易触发)。

典型可触发:

T make(bool f) {T a, b;if (f) return a;else   return a;   // 所有路径同一个 a,更容易
}

可能阻碍 NRVO 的情形(编译器可能放弃):

  • 分支返回不同的具名对象(a 或 b);
  • 对返回对象取地址/绑定到引用逃逸
  • volatile 对象、复杂异常路径等。

启示:尽量统一返回同一个具名对象;或直接用 §2 的“返回临时”。

4. 不要写的反优化:return std::move(obj);

  • 对具名局部变量 objstd::move(obj) 会阻碍 NRVO,让编译器退化为移动构造(甚至在某些场景变成拷贝)。
  • 编译器会给出 -Wpessimizing-move(Clang/GCC)警告。

正确写法

T make() {T obj;// ... 填充 obj ...return obj;        // 让 NRVO 尽量触发;不要 std::move(obj)
}

5. 与移动语义的关系

  • RVO/NRVO 的收益 > 移动:因为连移动构造也被消除了(直接在目标位置构造)。
  • C++17 之后,返回临时常常无需考虑“要不要 std::move”,因为直接就不产生移动。

6. 设计与重构建议(实战导向)

  1. 返回按值(by value)——放心用
    现代 C++(17+)下,只要返回的是临时或满足 NRVO 条件的局部,性能非常好;接口更简单、安全。

  2. 工厂函数优先返回临时

    static T make_xxx(args...) {return T(args...);      // 保证省略
    }
    
  3. 统一返回点
    需要做分支初始化时,可以用一处返回以帮助 NRVO:

    T make(bool f) {T obj = f ? T(1) : T(2);// ... 进一步配置 obj ...return obj;             // 触发 NRVO 的机会更高
    }
    
  4. 容器就地构造
    RVO/NRVO 解决“函数返回值”的搬运;而容器内部建议 emplace_back(...),避免中间对象:

    vec.emplace_back(args...);  // 直接就地构造
    
  5. 避免返回参数/捕获变量
    函数参数、lambda 捕获的对象不是局部自动对象,不享受 NRVO

    T f(T x) { return x; } // 常规是移动/拷贝,非 NRVO 对象
    

7. 诊断与验证

  • 编译期警告:-Wpessimizing-move(避免“画蛇添足”的 std::move)。
  • 观察构造次数:可在类型的拷贝/移动构造里打印日志对比 -O2-fno-elide-constructors
  • 主流优化开关:-O2/-O3;无需专门打开 RVO 开关。
    调试 RVO 行为时可临时加:-fno-elide-constructors(GCC/Clang)。

8. 常见 Q&A

Q:返回 std::optional<T> 会影响 RVO 吗?
A:return std::optional<T>{T(args)};T(args) 的构造仍受 C++17 prvalue 规则优化;同时可改为 return std::optional<T>(std::in_place, args...) 进一步避免中间层次。

Q:聚合类型/结构体大对象能否放心按值返回?
A:C++17 起可放心。按值返回+RVO/NRVO 通常等价于“直接在调用方栈上构造”,无多余移动。

Q:异常会破坏 RVO/NRVO 吗?
A:标准允许实现自由,但主流编译器在无复杂控制流时仍能很好地做 NRVO;返回临时的强制省略照常生效。

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

相关文章:

  • ethercat 环型拓扑(Ring Topology)
  • 颠覆PD快充、工业控制与智能家电等领域高CTR,高隔离电压高可靠性光电耦合器OCT1018/OCT1019
  • 【机器学习入门】8.1 降维的概念和意义:一文读懂降维的概念与意义 —— 从 “维度灾难” 到低维嵌入
  • 黄骅市旅游景点有哪些盐城网站关键词优化
  • 对于网站建设的调查问卷爱南宁app官网下载
  • 一文读懂 YOLOv1 与 YOLOv2:目标检测领域的早期里程碑
  • 在 Windows 10/11 LTSC等精简系统中安装Winget和微软应用商店,Windows Server安装Microsoft Store的应用
  • A2A架构详解
  • 基础 - SQL命令速查
  • logo图片素材大全sem和seo都包括什么
  • 把 AI“缝”进布里:生成式编织神经网络让布料自带摄像头
  • 岳阳建网站长沙网站优化价格
  • [Sora] 分布式训练 | 并行化策略 | `plugin_type` | `booster.boost()`
  • Linux系统函数link、unlink与dentry的关系及使用注意事项
  • 安卓手机 IP 切换指南:告别卡顿,轻松换 IP
  • 微服务拆分:领域驱动设计,单体应用如何平滑迁移?
  • 企业网站推广的形式有哪些福州网站推广排名
  • 关键词优化网站排名群英云服务器
  • nano-GPT:最小可复现的GPT实操
  • 网站建设公众号wordpress中文模板下载地址
  • 菜单及库(Num28)
  • super()核心作用是调用父类的属性/方法
  • 【Win32 多线程程序设计基础第三章笔记】
  • CentOS 7 FTP安装与配置详细介绍
  • 网页设计跟网站建设的区别淘宝店铺运营推广
  • 机器学习使用GPU
  • 做网站分为哪些功能的网站找工作网
  • 湖南粒界教育科技有限公司:专注影视技能培养,AI辅助教学提升学员就业竞争力
  • 【系统分析师】写作框架:静态测试方法及其应用
  • React useEffect组件渲染执行操作 组件生命周期 监视器 副作用