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次拷贝构造函数:
-
一次构造函数调用:在函数
f()内部,std::vector<int> v;这行代码会调用std::vector<int>的默认构造函数来创建局部对象v。 -
两次拷贝构造函数调用:
- 第一次是在
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++ 函数返回值优化
本文中部分内容来自下面的文章,还有一部分来自智谱清言 C 返回值优化_c 局部变量返回优化-CSDN博客 elision:省略 copy elision:拷贝省略 RVO (Return Value Optimization):返回值优化 ------ 我最近也遇到了上面博文中说到的问题&…...
c++源码阅读__ThreadPool__正文阅读
一. 简介 本章我们开始阅读c git 高星开源项目ThreadPool, 这是一个纯c的线程池项目, 并且代码量极小, 非常适合新手阅读 git地址: progschj / ThreadPool 二. 前提知识 为了面对不同读者对c掌握情况不同的情况, 这里我会将基本上稍微值得一说的前提知识点, 全部专门写成一篇…...
关于ES的查询
查询结果那么多字段都是什么? 为什么会提到这个问题呢,因为默认ES查询的结果会有很多信息,我们可能并不希望要那么多数据,所以你需要了解这些字段都表示什么,并正确的返回和使用它们。 took– Elasticsearch 运行查询…...
数据结构初识
目录 1.初识 2.时间复杂度 常见时间复杂度举例: 3.空间复杂度 4.包装类&简单认识泛型 4.1装箱和拆箱 5.泛型 6.泛型的上界 7.泛型方法 8.List接口 1.初识 1.多画图 2.多思考 3.多写代码 4.多做题 牛客网-题库/在线编程/剑指offer 算法篇:…...
保存数据到Oracle时报错ORA-17004: 列类型无效: 1111
1、问题描述: 关键信息:Mybatis;Oracle (1)保存信息到Oracle时报错: Caused by: org.apache.ibatis.type.TypeException: Error setting null for parameter #10 with JdbcType OTHER . Try setting a dif…...
Excel——宏教程(1)
Microsoft excel是一款功能非常强大的电子表格软件。它可以轻松地完成数据的各类数学运算,并用各种二维或三维图形形象地表示出来,从而大大简化了数据的处理工作。但若仅利用excel的常用功能来处理较复杂的数据,可能仍需进行大量的人工操作。…...
论文浅尝 | MindMap:知识图谱提示激发大型语言模型中的思维图(ACL2024)
笔记整理:和东顺,天津大学硕士,研究方向为软件缺陷分析 论文链接:https://aclanthology.org/2024.acl-long.558/ 发表会议:ACL 2024 1. 动机 虽然大语言模型(LLMs)已经在自然语言理解和生成任务…...
第6章:TDengine 标签索引和删除数据
TDengine 标签索引和删除数据 目标 掌握标签索引的创建、删除掌握超表、子表创建以及数据删除删除数据 删除数据是 TDengine 提供的根据指定时间段删除指定表或超级表中数据记录的功能,方便用户清理由于设备故障等原因产生的异常数据。 注意:删除数据并不会立即释放该表所…...
【微软:多模态基础模型】(5)多模态大模型:通过LLM训练
欢迎关注[【youcans的AGI学习笔记】](https://blog.csdn.net/youcans/category_12244543.html)原创作品 【微软:多模态基础模型】(1)从专家到通用助手 【微软:多模态基础模型】(2)视觉理解 【微…...
海外带云仓多语言商城源码,多语言多商家云仓一键代发商城
新增海外仓,云仓国际供应链系统,商家可登陆云仓进行批量发货 商城修复了一些bug以及增加了订单数字提示,优化加载速度,二开了一些细微功能 基于 PHP Laravel 框架开发的一款 Web 商城系统。 1.前端多国语言自由切换,…...
android:taskAffinity 对Activity退出时跳转的影响
android:taskAffinity 对Activity跳转的影响 概述taskAffinity 的工作机制taskAffinity对 Activity 跳转的影响一个实际的开发问题总结参考 概述 在 Android 开发中,任务栈(Task)是一个核心概念。它决定了应用程序的 Activity 如何相互交互以…...
Apache Dolphinscheduler数据质量源码分析
Apache DolphinScheduler 是一个分布式、易扩展的可视化数据工作流任务调度系统,广泛应用于数据调度和处理领域。 在大规模数据工程项目中,数据质量的管理至关重要,而 DolphinScheduler 也提供了数据质量检查的计算能力。本文将对 Apache Do…...
solana链上智能合约开发案例一则
环境搭建 安装Solana CLI:Solana CLI是开发Solana应用的基础工具。你可以通过官方文档提供的安装步骤,在本地环境中安装适合你操作系统的Solana CLI版本。安装完成后,使用命令行工具进行配置,例如设置网络环境(如开发网…...
使用 PyTorch 实现 ZFNet 进行 MNIST 图像分类
在本篇博客中,我们将通过两个主要部分来演示如何使用 PyTorch 实现 ZFNet,并在 MNIST 数据集上进行训练和测试。ZFNet(ZFNet)是基于卷积神经网络(CNN)的图像分类模型,广泛用于图像识别任务。 环…...
车轮上的科技:Spring Boot汽车新闻集散地
1系统概述 1.1 研究背景 随着计算机技术的发展以及计算机网络的逐渐普及,互联网成为人们查找信息的重要场所,二十一世纪是信息的时代,所以信息的管理显得特别重要。因此,使用计算机来管理汽车资讯网站的相关信息成为必然。开发合适…...
IDEA2023 SpringBoot整合Web开发(二)
一、SpringBoot介绍 由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的初始搭建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置。SpringBoot提供了一种新的编程范式,可以更加快速便捷…...
国产三维CAD 2025新动向:推进MBD模式,联通企业设计-制造数据
本文为CAD芯智库原创整理,未经允许请勿复制、转载! 上一篇文章阿芯分享了影响企业数字化转型的「MBD」是什么、对企业优化产品设计流程有何价值——这也是国产三维CAD软件中望3D 2024发布会上,胡其登先生(中望软件产品规划与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 定义(支持 Batch\Streaming) Lookup Join 其实就是维表 Join,比如拿离线数仓来说,常常会有用户画像,设备画像等数据,而对应到实时数仓场景中,这种实时获取外部缓存的 Join 就叫做维…...
Elasticsearch retrievers 通常与 Elasticsearch 8.16.0 一起正式发布!
作者:来自 Elastic Panagiotis Bailis Elasticsearch 检索器经过了重大改进,现在可供所有人使用。了解其架构和用例。 在这篇博文中,我们将再次深入探讨检索器(retrievers)。我们已经在之前的博文中讨论过它们…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
rnn判断string中第一次出现a的下标
# coding:utf8 import torch import torch.nn as nn import numpy as np import random import json""" 基于pytorch的网络编写 实现一个RNN网络完成多分类任务 判断字符 a 第一次出现在字符串中的位置 """class TorchModel(nn.Module):def __in…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
