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

C++ 函数返回值优化

本文中部分内容来自下面的文章,还有一部分来自智谱清言 

C++ 返回值优化_c++ 局部变量返回优化-CSDN博客

elision:省略

copy elision:拷贝省略

RVO (Return Value Optimization):返回值优化

------

我最近也遇到了上面博文中说到的问题:

观察这段代码:

std::vector<int> f() {std::vector<int> v;// do some thing with vreturn v;
}std::vector<int> test = f();

------

在C++中,当返回一个局部对象时,会发生以下事情:

拷贝返回:默认情况下,返回局部对象时,会通过拷贝构造函数创建返回值的副本

这意味着在函数返回后,局部对象被销毁,但是它的副本会被用来初始化调用处的变量

------

在这个例子中,返回局部对象v时,会通过拷贝构造函数创建返回值的副本[假设是temp]

这意味着在函数返回后,局部对象 v 被销毁,但是它的副本temp会被用来初始化调用处的变量test

------

移动语义(C++11及以后版本)

如果编译器支持返回值优化(RVO,Return Value Optimization)或者具名返回值优化(NRVO,Named Return Value Optimization),那么在返回 v 时,编译器可能会直接在调用者作用域构造 test,从而避免了额外的拷贝。

如果 std::vector<int> 支持移动构造函数,编译器还可能会使用移动语义,这意味着 v 的资源(如动态分配的内存)会被移动到 test 中,而不是复制,从而提高效率。

------ 

拷贝返回的话,共调用了1次构造函数,2次拷贝构造函数:

  1. 一次构造函数调用:在函数 f() 内部,std::vector<int> v; 这行代码会调用 std::vector<int> 的默认构造函数来创建局部对象 v

  2. 两次拷贝构造函数调用

    • 第一次是在 return v; 语句执行时,这时会创建一个 v 的副本,用于返回给函数的调用者
    • 第二次是在函数外部接收返回值时,即 std::vector<int> test = f(); 这行代码,这里 test 通过拷贝构造函数使用 f() 返回的 v 的副本[假设是temp]来初始化。

------ 

值得注意的是,现代C++编译器通常会应用返回值优化RVO)或具名返回值优化NRVO),在这种情况下,编译器可能会优化掉不必要的拷贝。

------

如果编译器能够应用这种优化,那么实际上可能只会有一次构造函数调用,即使是在返回局部对象时。在这种情况下,编译器会在调用者作用域直接构造 test,而不是在函数内部创建一个副本[假设是temp]然后拷贝它。

------

例如,如果编译器应用了RVO/NRVO,那么上面的代码在优化后的汇编代码中,可能会直接在 test 的位置构造 std::vector<int>,从而避免了额外的拷贝。

如果 std::vector<int> 支持移动语义(在C++11及以后版本中),编译器还可能会使用移动构造函数来进一步提高效率。

---------

对于上面的例子,通过返回值优化(RVO)或具名返回值优化(NRVO),编译器可以省略掉两次不必要的拷贝构造函数调用,只会调用一次构造函数。

具体来说:

  • RVO(Return Value Optimization):当编译器检测到函数返回的是一个局部对象,并且该局部对象是直接返回的没有经过任何中间步骤),编译器可能会直接在调用者的栈上构造这个对象,而不是在函数内部构造然后再拷贝。

  • NRVO(Named Return Value Optimization):这是RVO的一种特殊情况,当返回的局部对象有名字时,编译器可能会使用NRVO。

------

对于上面的示例,我猜:会使用NRVO:

编译器检测到函数返回的是局部对象v,并且该局部对象是直接返回的没有经过任何中间步骤),编译器会直接在调用者的栈上构造对象test,而不是在函数内部构造v然后再拷贝到temp再拷贝到test

------

如果没有应用RVO/NRVO,但编译器支持移动语义(C++11及以后版本),

并且 std::vector<int> 支持移动构造函数,那么编译器可能会使用移动构造函数来代替拷贝构造函数,这样仍然可以避免拷贝,但会调用一次移动构造函数。在这种情况下,总共会有一次构造函数调用一次移动构造函数调用

------

移动构造函数在何时被调用?

当对象即将被销毁,并且其资源可以被移动到另一个对象时

在函数 f() 返回局部对象 v 时,局部对象 v 将要离开其作用域并被销毁

如果此时 v 的资源(如动态分配的内存)可以被移动而不是复制,那么编译器会调用移动构造函数来将 v 的资源移动到将要接收返回值的对象test中。

------

总结:

  • 如果编译器应用了RVO/NRVO:总共一次构造函数调用。
  • 如果编译器没有应用RVO/NRVO,但使用了移动语义:总共一次构造函数调用和一次移动构造函数调用。
  • 如果编译器既没有应用RVO/NRVO,也没有使用移动语义:总共一次构造函数调用和两次拷贝构造函数调用。不过,在现代编译器中,这种情况不太可能发生,因为它们通常会利用RVO/NRVO或移动语义来优化代码。

------

相关文章:

C++ 函数返回值优化

本文中部分内容来自下面的文章&#xff0c;还有一部分来自智谱清言 C 返回值优化_c 局部变量返回优化-CSDN博客 elision:省略 copy elision&#xff1a;拷贝省略 RVO (Return Value Optimization)&#xff1a;返回值优化 ------ 我最近也遇到了上面博文中说到的问题&…...

c++源码阅读__ThreadPool__正文阅读

一. 简介 本章我们开始阅读c git 高星开源项目ThreadPool, 这是一个纯c的线程池项目, 并且代码量极小, 非常适合新手阅读 git地址: progschj / ThreadPool 二. 前提知识 为了面对不同读者对c掌握情况不同的情况, 这里我会将基本上稍微值得一说的前提知识点, 全部专门写成一篇…...

关于ES的查询

查询结果那么多字段都是什么&#xff1f; 为什么会提到这个问题呢&#xff0c;因为默认ES查询的结果会有很多信息&#xff0c;我们可能并不希望要那么多数据&#xff0c;所以你需要了解这些字段都表示什么&#xff0c;并正确的返回和使用它们。 took– Elasticsearch 运行查询…...

数据结构初识

目录 1.初识 2.时间复杂度 常见时间复杂度举例&#xff1a; 3.空间复杂度 4.包装类&简单认识泛型 4.1装箱和拆箱 5.泛型 6.泛型的上界 7.泛型方法 8.List接口 1.初识 1.多画图 2.多思考 3.多写代码 4.多做题 牛客网-题库/在线编程/剑指offer 算法篇&#xff1a…...

保存数据到Oracle时报错ORA-17004: 列类型无效: 1111

1、问题描述&#xff1a; 关键信息&#xff1a;Mybatis&#xff1b;Oracle &#xff08;1&#xff09;保存信息到Oracle时报错&#xff1a; Caused by: org.apache.ibatis.type.TypeException: Error setting null for parameter #10 with JdbcType OTHER . Try setting a dif…...

Excel——宏教程(1)

Microsoft excel是一款功能非常强大的电子表格软件。它可以轻松地完成数据的各类数学运算&#xff0c;并用各种二维或三维图形形象地表示出来&#xff0c;从而大大简化了数据的处理工作。但若仅利用excel的常用功能来处理较复杂的数据&#xff0c;可能仍需进行大量的人工操作。…...

论文浅尝 | MindMap:知识图谱提示激发大型语言模型中的思维图(ACL2024)

笔记整理&#xff1a;和东顺&#xff0c;天津大学硕士&#xff0c;研究方向为软件缺陷分析 论文链接&#xff1a;https://aclanthology.org/2024.acl-long.558/ 发表会议&#xff1a;ACL 2024 1. 动机 虽然大语言模型&#xff08;LLMs&#xff09;已经在自然语言理解和生成任务…...

第6章:TDengine 标签索引和删除数据

TDengine 标签索引和删除数据 目标 掌握标签索引的创建、删除掌握超表、子表创建以及数据删除删除数据 删除数据是 TDengine 提供的根据指定时间段删除指定表或超级表中数据记录的功能,方便用户清理由于设备故障等原因产生的异常数据。 注意:删除数据并不会立即释放该表所…...

【微软:多模态基础模型】(5)多模态大模型:通过LLM训练

欢迎关注[【youcans的AGI学习笔记】](https://blog.csdn.net/youcans/category_12244543.html&#xff09;原创作品 【微软&#xff1a;多模态基础模型】&#xff08;1&#xff09;从专家到通用助手 【微软&#xff1a;多模态基础模型】&#xff08;2&#xff09;视觉理解 【微…...

海外带云仓多语言商城源码,多语言多商家云仓一键代发商城

新增海外仓&#xff0c;云仓国际供应链系统&#xff0c;商家可登陆云仓进行批量发货 商城修复了一些bug以及增加了订单数字提示&#xff0c;优化加载速度&#xff0c;二开了一些细微功能 基于 PHP Laravel 框架开发的一款 Web 商城系统。 1.前端多国语言自由切换&#xff0c;…...

android:taskAffinity 对Activity退出时跳转的影响

android:taskAffinity 对Activity跳转的影响 概述taskAffinity 的工作机制taskAffinity对 Activity 跳转的影响一个实际的开发问题总结参考 概述 在 Android 开发中&#xff0c;任务栈&#xff08;Task&#xff09;是一个核心概念。它决定了应用程序的 Activity 如何相互交互以…...

Apache Dolphinscheduler数据质量源码分析

Apache DolphinScheduler 是一个分布式、易扩展的可视化数据工作流任务调度系统&#xff0c;广泛应用于数据调度和处理领域。 在大规模数据工程项目中&#xff0c;数据质量的管理至关重要&#xff0c;而 DolphinScheduler 也提供了数据质量检查的计算能力。本文将对 Apache Do…...

solana链上智能合约开发案例一则

环境搭建 安装Solana CLI&#xff1a;Solana CLI是开发Solana应用的基础工具。你可以通过官方文档提供的安装步骤&#xff0c;在本地环境中安装适合你操作系统的Solana CLI版本。安装完成后&#xff0c;使用命令行工具进行配置&#xff0c;例如设置网络环境&#xff08;如开发网…...

使用 PyTorch 实现 ZFNet 进行 MNIST 图像分类

在本篇博客中&#xff0c;我们将通过两个主要部分来演示如何使用 PyTorch 实现 ZFNet&#xff0c;并在 MNIST 数据集上进行训练和测试。ZFNet&#xff08;ZFNet&#xff09;是基于卷积神经网络&#xff08;CNN&#xff09;的图像分类模型&#xff0c;广泛用于图像识别任务。 环…...

车轮上的科技:Spring Boot汽车新闻集散地

1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及&#xff0c;互联网成为人们查找信息的重要场所&#xff0c;二十一世纪是信息的时代&#xff0c;所以信息的管理显得特别重要。因此&#xff0c;使用计算机来管理汽车资讯网站的相关信息成为必然。开发合适…...

IDEA2023 SpringBoot整合Web开发(二)

一、SpringBoot介绍 由Pivotal团队提供的全新框架&#xff0c;其设计目的是用来简化Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置&#xff0c;从而使开发人员不再需要定义样板化的配置。SpringBoot提供了一种新的编程范式&#xff0c;可以更加快速便捷…...

国产三维CAD 2025新动向:推进MBD模式,联通企业设计-制造数据

本文为CAD芯智库原创整理&#xff0c;未经允许请勿复制、转载&#xff01; 上一篇文章阿芯分享了影响企业数字化转型的「MBD」是什么、对企业优化产品设计流程有何价值——这也是国产三维CAD软件中望3D 2024发布会上&#xff0c;胡其登先生&#xff08;中望软件产品规划与GTM中…...

ubuntu 之 安装mysql8

安装 # 如果 ubuntu 版本 > 20.04 则不用执行 wget 这步 wget https://dev.mysql.com/get/mysql-apt-config_0.8.12-1_all.debsudo apt-get updatesudo apt-get install mysql-server mysql-client 安装过程中如果没有提示输入密码 sudo cat /etc/mysql/debian.cnf # 查…...

Flink Lookup Join(维表 Join)

Lookup Join 定义&#xff08;支持 Batch\Streaming&#xff09; Lookup Join 其实就是维表 Join&#xff0c;比如拿离线数仓来说&#xff0c;常常会有用户画像&#xff0c;设备画像等数据&#xff0c;而对应到实时数仓场景中&#xff0c;这种实时获取外部缓存的 Join 就叫做维…...

Elasticsearch retrievers 通常与 Elasticsearch 8.16.0 一起正式发布!

作者&#xff1a;来自 Elastic Panagiotis Bailis Elasticsearch 检索器经过了重大改进&#xff0c;现在可供所有人使用。了解其架构和用例。 在这篇博文中&#xff0c;我们将再次深入探讨检索器&#xff08;retrievers&#xff09;。我们已经在之前的博文中讨论过它们&#xf…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

libfmt: 现代C++的格式化工具库介绍与酷炫功能

libfmt: 现代C的格式化工具库介绍与酷炫功能 libfmt 是一个开源的C格式化库&#xff0c;提供了高效、安全的文本格式化功能&#xff0c;是C20中引入的std::format的基础实现。它比传统的printf和iostream更安全、更灵活、性能更好。 基本介绍 主要特点 类型安全&#xff1a…...

c# 局部函数 定义、功能与示例

C# 局部函数&#xff1a;定义、功能与示例 1. 定义与功能 局部函数&#xff08;Local Function&#xff09;是嵌套在另一个方法内部的私有方法&#xff0c;仅在包含它的方法内可见。 • 作用&#xff1a;封装仅用于当前方法的逻辑&#xff0c;避免污染类作用域&#xff0c;提升…...

2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案

一、延迟敏感行业面临的DDoS攻击新挑战 2025年&#xff0c;金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征&#xff1a; AI驱动的自适应攻击&#xff1a;攻击流量模拟真实用户行为&#xff0c;差异率低至0.5%&#xff0c;传统规则引…...