C++对象拷贝时的优化编译

news2024/11/16 4:23:05

在现代编译器中,当我们在 C++中进行对象的拷贝操作时,编译器并非只是机械地执行逐字节的复制。相反,它会进行优化,避免不必要的拷贝构造等等,这种优化包括“返回值优化”(RVO),“拷贝省略” 等等。以下代码运行结果是在vs2022下实现的。

#include<iostream>
using namespace std;

class A
{
public:
	A(int a = 0)
		:_a1(a)
	{
		cout << "A(int a)" << endl;
	}
    //拷贝构造
	A(const A& aa)
		:_a1(aa._a1)
	{
		cout << "A(const A& aa)" << endl;
	}
	A& operator=(const A& aa)
	{
		cout << "A& operator=(const A& aa)" << endl;
		if (this != &aa)
		{
			_a1 = aa._a1;
		}
		return *this;
	}
    //析构
	~A()
	{
		cout << "~A()" << endl;
	}
private:
	int _a1 = 1;
};
void f1(A aa)
{}
A f2()
{
	A aa;
	return aa;
}

1.内置类型转换为自定义类型的优化

int main()
{
    A aa = 1;
    return 0;
}

    在语法上来看,也就是没有优化的情况下,(1)编译器先调用默认构造函数,在栈上创建临时对象,传入参数值1初始化临时对象的成员变量,(2)再将这个临时对象去拷贝构造给aa,(3)aa被初始化成功后析构这个临时对象,(4)等到程序结束时再析构aa

    从下面的结果来看,也就是优化之后,并没有调用拷贝构造,(1)编译器可能直接调用默认构造函数初始化aa,而不创建临时对象和调用拷贝参数,(2)然后在程序结束时析构aa。

2.传值传参时的优化

void f1(A aa)
{}
int main()
{
	A aa1;
	f1(aa1);
    retrun 0;
}

从语法上看,(1)当执行A aa1时,编译器会调用A类的默认构造函数。由于没有提供参数,默认构造函数A(int n = 0)会被调用,_a1被初始化为0。(2)随后执行f1(aa1),编译器会调用A类拷贝构造函数将aa1的值拷贝到临时对象aa中,(3)然后进入函数f1, 该函数结束时调用析构函数析构aa,(4)最后main函数结束时析构aa1。从结果上来看,此处没有优化。

3.隐式类型

void f1(A aa)
{}
int main()
{	
 //隐式类型,连续构造+拷⻉构造->优化为直接构造
	f1(1);
    return 0;
}

从语法上来看,(1)当调用f1(1)时,编译器调用A的默认构造函数将整数1隐式转换为A类对象(2)进入函数f1,由于f1的参数是按值传递的,A类的临时对象aa被创建,并且刚刚创建的对象会被拷贝构造到临时对象aa中,(3)当函数f1结束时,析构aa。当main函数结束时,此处由于没有其它对象,所以没有再调用析构函数。

优化过之后,(1)编辑器可能直接会直接在f1的参数位置调用默认构造函数,使用参数1进行构造,(2)而不是先创建一个临时对象再拷贝,因此没有拷贝构造。(3)在f1内部,aa直接引用构造函数,到函数f1结束时,析构aa。得到了下面的结果                                                                                                                                                   

4.传值返回

A f2()
{
	A aa;
	return aa;
}
int main()
{
	// 传值返回
    // 返回时⼀个表达式中,连续拷⻉构造+拷⻉构造->优化⼀个拷⻉构造 (vs2019 debug)
	// ⼀些编译器会优化得更厉害,进⾏跨⾏合并优化,直接变为构造。(vs2022 debug)
    //构造+拷贝构造-》直接构造
	A aa2 = f2();
}

从语法上来看,(1)当调用A aa2 = f2();时,程序进入f2函数,首先创建局部对象aa,调用默认构造函数初始化aa,(2)返回时会触发拷贝构造函数,创建一个临时对象用于返回值传递,(3)在main函数中临时对象初始化aa2再次触发拷贝构造,(4)当f2函数执行完毕,编译器会调用aa的析构函数,(5)当main函数结束时调用aa2的析构函数

优化后,(1)在函数f2中调用了默认构造函数创建一个A类对象aa2,(2)从结果上来看,编译器可能是只创建了aa2,将aa类似一个指针的效果指向aa2,因此只在在main函数结束时调用了析构函数析构aa2,而没有析构aa

A f2()
{
	A aa;
    cout << &aa2 << endl;
	return aa;
}
int main()
{
    cout << &aa2 << endl;
	A aa2 = f2();
}	

从下面的图中我们可以看到,aa和aa2的地址是相同的。 

这篇文章主要目的是为了介绍编译器的对代码的优化,以及学习程序运行的语法,可能有表述不严谨的地方,欢迎大家探讨纠正。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2151123.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaSE——String类

一、字符串构造 注意&#xff1a;String是引用类型&#xff0c;内部并不存储字符串本身。 有三种方式&#xff1a; public class Test1 {public static void main(String[] args) {// 使用常量串构造String s1 "hello java";System.out.println(s1);// 直接newSt…

JavaEE:探索网络世界的魅力——玩转UDP编程

文章目录 UDPUDP的特点UDP协议端格式校验和前置知识校验和具体是如何工作的? UDP UDP的特点 UDP传输的过程类似于寄信. 无连接: 知道对端的IP和端口号就直接进行传输,不需要建立连接.不可靠: 没有确认机制,没有重传机制,如果因为网络故障导致该段无法到达对方,UDP协议也不会…

Linux:make,Makefile

hello&#xff0c;各位小伙伴&#xff0c;本篇文章跟大家一起学习《Linux&#xff1a;make&#xff0c;Makefile》&#xff0c;感谢大家对我上一篇的支持&#xff0c;如有什么问题&#xff0c;还请多多指教 &#xff01; 如果本篇文章对你有帮助&#xff0c;还请各位点点赞&…

技术成神之路:设计模式(十四)享元模式

介绍 享元模式&#xff08;Flyweight Pattern&#xff09;是一种结构性设计模式&#xff0c;旨在通过共享对象来有效地支持大量细粒度的对象。 1.定义 享元模式通过将对象状态分为内部状态&#xff08;可以共享&#xff09;和外部状态&#xff08;不可共享&#xff09;&#xf…

为什么我不建议你考CCNA/HCIA这种初级认证

CCNA和HCIA&#xff0c;这两个证书可能是许多刚入门的网络工程师第一个听说的认证。作为入门级网络认证&#xff0c;CCNA是思科公司推出的&#xff0c;提供了网络基础的全面知识&#xff0c;而HCIA则是华为的基础认证&#xff0c;覆盖了网络技术的基本原理。 这些认证的目的是帮…

2023-03 GESP Python一级试卷

一、单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09; 1.以下不属于计算机输入设备的有&#xff08; &#xff09;。 ​ A&#xff0e;键盘 ​ B&#xff0e;音箱 ​ C&#xff0e;鼠标 ​ D&#xff0e;传感器 2.计算机系统中存储的基本单位用 B 来表示&am…

用友U8二次开发工具KK-FULL-*****-EFWeb使用方法

1、安装: 下一步&#xff0c;下一步即可。弹出黑框不要关闭&#xff0c;让其自动执行并关闭。 2、服务配置&#xff1a; 输入服务器IP地址&#xff0c;选择U8数据源&#xff0c;输入U8用户名及账号&#xff0c;U8登录日期勾选系统日期。测试参数有效性&#xff0c;提示测试通过…

洞悉市场先机,Vatee万腾平台助力企业精准决策

在瞬息万变的商业环境中&#xff0c;每一个市场动向都可能成为企业兴衰的关键。因此&#xff0c;洞悉市场先机&#xff0c;做出精准决策&#xff0c;成为了企业持续发展和保持竞争力的核心要素。Vatee万腾平台&#xff0c;凭借其强大的数据分析能力和智能化技术&#xff0c;正成…

对象检测边界框损失 – 从IOU到ProbIOU

1.概述 目标检测损失函数的选择在目标检测问题建模中至关重要。通常&#xff0c;目标检测需要两个损失函数&#xff0c;一个用于对象分类&#xff0c;另一个用于边界框回归&#xff08;BBR&#xff09;。本文将重点介绍 IoU 损失函数&#xff08;GIoU 损失、DIoU 损失和 CIoU 损…

【补码运算】设x=FEH,当x分别为下列情况时写出其对应的十进制真值(写出计算过程):(1)为原码(2)为补码。

欢迎来到我的技术博客&#xff01; &#x1f389; 这里不仅有满满的编程干货和学习资源&#xff0c;我的某站账号也为你准备了更多实用的技术视频和知识分享。 &#x1f449; 点击关注我的小破站账号&#xff0c;获取更多编程技巧和学习资源&#xff01; 小破站主页 题目&…

搜索引擎onesearch3实现解释和升级到Elasticsearch v8系列(三)-文档

文档 文档服务负责写入&#xff0c;包括批量&#xff1b;id获取文档&#xff1b;nested写入 写入文档 写入文档主要是构建IndexRequest&#xff0c;索引请求 Elasticsearch v8构建文档索引请求简单很多&#xff0c;可以直接接受Map数据 批量写入文档 批量操作可以融合增删改…

肥胖成因:饮食之外,消耗吸收慢是关键因素

肥胖问题一直被现代社会所关注&#xff0c;不可否认&#xff0c;饮食是影响胖瘦的重要因素之一。高热量、高油脂的食物摄入过多&#xff0c;也确实会导致热量油脂过剩&#xff0c;堆积储存进身体内进而养肥身体。可在正常情况中&#xff0c;就算是消耗吸收率一般的人&#xff0…

从源码看透 Ptmalloc:堆内存分配与释放的背后

&#x1f6f8;0. 前言 内存管理是个很复杂的东西&#xff0c;一般的程序员在写应用层代码的时候根本就不会关注内存的使用&#xff0c;尤其是 GC 语言自带垃圾回收机制&#xff0c;很多同学都使用过 C 语言中的 malloc&#xff0c;但很少有人能知道 malloc 其实是个很复杂的实现…

tomcat服务搭建部署ujcms网站

tomcat服务搭建部署ujcms网站 关闭selinux和防火墙 setenforce 0 && systemctl stop firewalld安装java环境 #卸载原有java8环境 yum remove java*#上传java软件包&#xff0c;并解压缩 tar -xf openjdk-11.0.1_linux-x64_bin.tar.gz && mv jdk-11.0.1 jdk11…

Android Perfetto 学习

1、如何抓取性能日志 方式1、通过手机里的System Tracing抓取 1、点击Settings->System->Developer options->System Tracing->Record trace 打开 2、操作完成后&#xff0c;点击Settings->System->Developer options->System Tracing->Record trace…

C++自动寻径算法

测试 #include <iostream> #include "source/AStar.hpp"int main() {AStar::Generator generator;generator.setWorldSize({25, 25});generator.setHeuristic(AStar::Heuristic::euclidean);generator.setDiagonalMovement(true);generator.addCollision({1, …

Vue 实现高级穿梭框 Transfer 封装

文章目录 01 基础信息1.1. 技术栈1.2. 组件设计a. 竖版设计稿b. 横版设计稿 02 技术方案&#xff08;1&#xff09;初定义数据&#xff08;2&#xff09;注意事项&#xff08;3&#xff09;逻辑草图 03 代码示例3.1. 组件使用3.2. 组件源码./TransferPlus/index.vue./TransferP…

爬虫----webpack

目录 一. 什么是webpack 出现的原因&#xff1a;同名函数 概念: 特征&#xff1a;大量缩进 webpack的格式 简单的webpack格式&#xff1a; 详细的webpack格式&#xff1a; 几个参数的运用 1. webpack数组形式 2. webpack对象格式 3.多个js文件打包 打印要扣的代码 …

【STM32 Blue Pill编程实例】-手机通过HC-05串口蓝牙控制LED

手机通过HC-05串口蓝牙控制LED 文章目录 手机通过HC-05串口蓝牙控制LED1、HC-05串口蓝牙模块介绍2、硬件准备和接线3、模块配置4、代码实现5、手机控制在本文中,我们介绍如何使用 STM32CubeIDE 和 HAL 库将 HC-05 蓝牙模块与 STM32 Blue Pill 开发板连接。 我们将使用 Android…

HarmonyOS 应用获取公钥和 MD5 指纹签名信息

鸿蒙版本获取 MD5 指纹和公钥可参考如下方式; 首先,通过 AGC 官网 将所需证书下载至本地; 其次,通过记事本或者文本编译器的方式将其正式打开,将其内容中前两项 BEGIN CERTIFICATE 和 END CERTIFICATE 的段落删除,仅保留最后一段中的内容(包括 BEGIN CERTIFICATE 和 END CERTI…