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

RVO和移动语义

  • RVO (Return Value Optimization):是关于函数返回值的优化。它能避免为函数返回的临时对象创建拷贝。
  • Pass-by-Value and Move:是关于函数参数传递的优化策略。它利用移动语义来接收参数,避免不必要的拷贝。

它们的应用场景完全不同,一个是“出”,一个是“进”。下面我们来详细分解一下。


1. RVO/NRVO:函数返回时的优化

RVO (Return Value Optimization) 和 NRVO (Named Return Value Optimization) 是编译器的一种优化技术,它可以在函数返回一个对象时,直接将这个对象构造在调用者指定的内存位置上,从而完全省略掉一次拷贝(或移动)构造。

示例:

std::string create_string() {std::string s = "hello world";return s; // 这里可能会发生 NRVO
}int main() {std::string main_s = create_string();
}

没有 RVO/NRVO 的逻辑步骤:

  1. create_string 函数内部,创建一个局部 std::string s
  2. return s; 时,将 s 拷贝/移动到一个临时的返回值对象中。
  3. main 函数中,main_s 通过这个临时返回值对象进行拷贝/移动构造。

有 RVO/NRVO 的实际步骤:

  1. 编译器非常聪明,它发现 create_string 的返回值将要初始化 main_s
  2. 于是,编译器直接在 main_s 的内存空间上构造了那个值为 "hello world" 的字符串。
  3. 中间的局部变量 s 和临时返回值对象都“消失”了。没有发生任何拷贝或移动

关键点:RVO/NRVO 是一种“消除”操作,它让拷贝/移动从始至终都没有发生。从 C++17 开始,在某些情况下,这种优化已经是强制性的。


2. Pass-by-Value and Move:函数参数传递的优化

这是我们在 EventLoopThreadPool 构造函数中讨论的场景。我们来看一下这个构造函数:

EventLoopThreadPool::EventLoopThreadPool(IEventLoop* baseLoop, std::string nameArg): baseLoop_(baseLoop),name_(std::move(nameArg)), // 从参数移动到成员变量started_(false),numThreads_(0),next_(0)
{
}

这里我们分析两种情况:

情况 A:传递一个右值(临时对象)

当你这样调用时:
EventLoopThreadPool pool(loop, "my-pool");

这里的 "my-pool" 是一个 const char*,它会隐式地构造一个 std::string 的临时对象(这是一个右值)。

逻辑步骤:

  1. 一个 std::string 临时对象被创建。
  2. 这个临时对象被 移动构造 到参数 nameArg 中。(注意:编译器通常会在这里进行一次类似 RVO 的优化,直接在 nameArg 的位置上构造临时对象,从而省略这次移动)。
  3. 在构造函数的初始化列表中,nameArg 通过 std::move 移动构造 到成员变量 name_ 中。

最终结果: 1 次构造 + 1 次移动。非常高效。

情况 B:传递一个左值(命名对象)

当你这样调用时:

std::string pool_name = "my-pool";
EventLoopThreadPool pool(loop, pool_name);

这里的 pool_name 是一个左值。

逻辑步骤:

  1. pool_name拷贝构造 到参数 nameArg 中。因为我们不能修改 pool_name 本身。
  2. 在构造函数的初始化列表中,nameArg 通过 std::move 移动构造 到成员变量 name_ 中。

最终结果: 1 次拷贝 + 1 次移动。

关键点:这种方式是通过 移动 来“窃取”参数 nameArg 的资源,而不是像 RVO 那样完全“消除”一个对象。它为处理左值和右值提供了一个统一且高效的接口。


总结与对比

特性RVO / NRVOPass-by-Value and Move
场景 (Context)函数返回值时函数参数传递时(特别是对于 “sink” 型参数,即要存起来的参数)
机制 (Mechanism)消除 (Elision) 拷贝/移动,直接在调用者内存中构造对象。通过移动 (Move) 来转移资源,避免深拷贝。
效果理想情况下,没有额外的构造、拷贝或移动。对于右值,有一次移动;对于左值,有一次拷贝和一次移动。
本质编译器的“魔法”,它改变了对象的构造地点。C++11 语言特性(右值引用和移动语义)的一种编程模式。

当您传递一个右值(例如 "my-pool")时,它和 RVO 的目标都是避免昂贵的拷贝,但实现路径不同:

  • RVO 是在函数返回时,通过“消除”操作实现的。
  • 我们的构造函数参数优化,是在函数调用时,通过移动语义来高效接收这个右值。
http://www.dtcms.com/a/572656.html

相关文章:

  • 阻塞队列 BlockingQueue 全解析:从 ArrayBlockingQueue 到 LinkedBlockingQueue
  • Autoware.universe多点导航和避障绕障设置
  • 计网6.1 网络应用模型
  • YOLO系列算法学习:YOLOv8:系列又一力作
  • 自动化测试-YAML
  • UnityGLTF 材质创建与赋值流程
  • 专业英文网站建设外贸业务怎么利用网站开发客户
  • 泰州网站建设策划做棋牌网站合法
  • uniapp开发ai对话app,使用百度语音识别用户输入内容并展示到页面上
  • 【XR技术介绍】Inside-Out Tracking:为何成为主流?核心技术:视觉SLAM原理通俗解读
  • Vue3 项目 GitLab CI/CD 自动构建并推送到 Harbor 教程
  • 【XR硬件系列】夸克 AI 眼镜预售背后:阿里用 “硬件尖刀 + 生态护城河“ 重构智能穿戴逻辑
  • 怎么查网站关键词排名个人网站设计企业
  • 金融机构如何用企业微信实现客户服务优化?
  • MD5 + SHA-1 详解
  • [Dify 实战] 对接飞书、企业微信等聊天系统的最佳实践与策略
  • Spring MVC 响应处理:页面、数据与状态配置详解
  • 图解 MySQL JOIN
  • 数据结构知识掌握
  • 利用MLPack插件在DuckDB中机器学习
  • 做电子书的网站很有名后来被关闭了东营市建设局官网
  • 企业微信可信IP配置的Python完美解决方案
  • 卫朋:IPD如何实现战略解码?三步翻译术
  • 德州市市长朱开国率队到访深兰科技,加速推进机器人产业落地与合作深化
  • Redis中的分布式锁
  • JVM核心知识整理《1》
  • 可以上传数据的网站开发图书页面设计模板
  • 09.MCP协议介绍
  • 彻底讲清楚 Kotlin 的 when 表达式
  • 济宁网站建设 果壳科技腾讯云主机