当前位置: 首页 > 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…...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

使用van-uploader 的UI组件,结合vue2如何实现图片上传组件的封装

以下是基于 vant-ui&#xff08;适配 Vue2 版本 &#xff09;实现截图中照片上传预览、删除功能&#xff0c;并封装成可复用组件的完整代码&#xff0c;包含样式和逻辑实现&#xff0c;可直接在 Vue2 项目中使用&#xff1a; 1. 封装的图片上传组件 ImageUploader.vue <te…...

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…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

2025季度云服务器排行榜

在全球云服务器市场&#xff0c;各厂商的排名和地位并非一成不变&#xff0c;而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势&#xff0c;对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析&#xff1a; 一、全球“三巨头”…...