【C++】构造函数和初始化列表的性能差距

构造函数和初始化列表的性能差距对比测试

1.说明

在C++类和对象中,你可能听到过更加推荐用初始化列表来初始化类内成员。如果类内成员是自定义类型,则只能在初始化列表中调用自定义类型的构造函数。

但初始化列表和在构造函数体内直接赋值有无性能差距呢?今天就用一份相对简单的代码来测试一下

2.测试

2.1 代码说明

首先是一个自定义类型,实现带缺省值的默认构造,拷贝构造和赋值重载这三个函数,并在内部新增打印来区分不同的函数

struct mytest {
public:mytest(int a = -1){_a = a;cout << "mytest() " << a << endl;}mytest(const mytest& st) {_a = st._a;cout << "mytest(copy) " << st._a << endl;}mytest& operator=(const mytest& st){_a = st._a;cout << "mytest operator= " << st._a << endl;return *this;}
private:int _a;
};

再在另外一个类中使用这个自定义类型

struct myclass {
public:myclass(const struct mytest& st, int b){cout << "myclass() _b:" << _b << endl;}struct mytest _sa;int _b;
};

此时构造函数就有两种写法,一种是在初始化列表中初始化这个自定义类型

	myclass(const struct mytest& st, int b):_sa(st),_b(b){cout << "myclass() _b:" << _b << endl;}

另外一种是在构造函数体内通过赋值重载来初始化这个自定义类型

    myclass(const struct mytest& st, int b){_sa = st;_b = b;cout << "myclass() _b:" << _b << endl;}

需要注意的是,这里的自定义类型传参采用了引用传参,并不会因此产生额外的拷贝!

主函数体如下,为了区分第一个mytest的构造函数,我在其后新增了一行输出作为分割

int main()
{mytest test_a(1);cout << "------" << endl;myclass test(test_a, 3);return 0;
}

2.2 测试

先来看看使用赋值初始化的方式,可以看到,虽然我们在初始化列表中什么都没有写,但是这里依旧调用了默认的构造函数(因为默认构造函数的缺省值给的是-1,这里能通过参数判断出来这并不是我们显式调用的构造)

调用了默认构造后,又通过赋值重载来初始化了一遍_sa,相当于两次初始化

image-20230824212849577

但如果调用初始化列表,则只会有一次拷贝构造,避免了额外的默认构造调用

image-20230824213021929

在linux下也测试过了,结果和VS2019相同

3.结论

结论就出来了:初始化列表能节省一次默认构造的调用,优化性能!

3.1 实际场景

在上面的场景中,性能差距可能并不会特别大,但是在下面的场景中可能就不一样了

struct mytest {
public:mytest(int sz = 1){_str = new char[sz];_sz = sz;cout << "mytest() " << sz << endl;}mytest(const mytest& st) {delete _str;// 需要先销毁原视的数据_str = new char[st._sz]; // 再创建一个新的_sz = st._sz;//省略拷贝数据的代码cout << "mytest(copy) " << st._sz << endl;}mytest& operator=(const mytest& st){delete _str;// 需要先销毁原视的数据_str = new char[st._sz]; // 再创建一个新的//省略拷贝数据的代码cout << "mytest& operator= " << st._sz << endl;return *this;}
private:char* _str;size_t _sz;
};struct myclass {
public:myclass(const struct mytest& st, int b):_sa(st),_b(b){//_sa = st;//_b = b;cout << "myclass() _b:" << _b << endl;}struct mytest _sa;int _b;
};

在这个场景中,因为mytest自定义类型的拷贝构造涉及到了深拷贝,此时就需要将已有的空间给销毁了,再new一片新的空间出来,再将数据给拷贝过去。

白白多了一层默认构造中的new空间的+拷贝构造中delete原有空间的消耗!

如果类中需要深拷贝的成员不止一个,那性能差距就更大!

所以在C++中,一律以初始化列表优先


这里顺带提一嘴初始化列表的小坑,也算是复习;

当你使用初始化列表来初始化类内成员的时候,初始化的顺序是类内成员声明的顺序,而不是初始化列表中的顺序!这点非常重要,如果顺序不对,可能会出现使用未定义(还没有初始化完成)的参数的bug!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Python机器学习】实验15 将Lenet5应用于Cifar10数据集

文章目录 CIFAR10数据集介绍1. 数据的下载2.修改模型与前面的参数设置保持一致3. 新建模型4. 从数据集中分批量读取数据5. 定义损失函数6. 定义优化器7. 开始训练8.测试模型 9. 手写体图片的可视化10. 多幅图片的可视化 思考题11. 读取测试集的图片预测值&#xff08;神经网络的…

L1-033 出生年 测试点全过

题目 以上是新浪微博中一奇葩贴&#xff1a;“我出生于1988年&#xff0c;直到25岁才遇到4个数字都不相同的年份。”也就是说&#xff0c;直到2013年才达到“4个数字都不相同”的要求。本题请你根据要求&#xff0c;自动填充“我出生于y年&#xff0c;直到x岁才遇到n个数字都不…

07-Numpy基础-伪随机数生成

numpy.random模块对Python内置的random进行了补充&#xff0c;增加了一些用于高效生成多种概率分布的样本值的函数。 例如&#xff0c;你可以用normal来得到一个标准正态分布的44样本数组&#xff1a; 而Python内置的random模块则只能一次生成一个样本值。从下面的测试结果中可…

C++day4(拷贝赋值函数、匿名对象、友元、常成员函数和常对象、运算符重载)

一、Xmind整理&#xff1a; 二、上课笔记整理&#xff1a; 1.day3作业订正&#xff1a;设计一个Per类&#xff0c;类中包含私有成员&#xff1a;姓名、年龄、指针成员身高... #include <iostream>using namespace std;//封装人 类 class Person { private:string name;…

【大模型AIGC系列课程 2-2】大语言模型的“第二大脑”

1. 大型语言模型的不足之处 很多人使用OpenAI提供的GPT系列模型时都反馈效果不佳。其中一个主要问题是它无法回答一些简单的问题。 ● 可控性:当我们用中文问AI一些关于事实的问题时,它很容易编造虚假答案。 ● 实时性:而当你询问它最近发生的新闻事件时,它会干脆地告诉你…

【使用深度学习的城市声音分类】使用从提取音频特征(频谱图)中提取的深度学习进行声音分类研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

四信5G工业路由器赋能5G LAN全连接工厂建设

5G作为“新基建”之首&#xff0c;肩负着驱动国民经济转型升级、促进实体经济与数字经济深度融合、满足各行各业高质量通信服务需求的重任。 随着5G技术的更新迭代&#xff0c;各行各业对网络的可靠性&#xff0c;确定性等提出更高的需求&#xff0c;5G LAN作为3GPP R16标准定…

【面试 反思】Retrofit源码与设计 7 连问

前言 在实际项目中往往是使用Retrofit来做网络请求工作。Retrofit采用RESTful风格&#xff0c;本质上只是对OkHttp进行封装&#xff0c;今天我们根据几个问题来进一步学习一下Retrofit的源码与设计思想。 1. 使用方法 直接看一下官方介绍的使用方法。 public final class S…

[MyBatis系列③]动态SQL

目录 1、简介 2、if标签 3、foreach标签 4、SQL抽取 ⭐MyBatis系列①&#xff1a;增删改查 ⭐MyBatis系列②&#xff1a;两种Dao开发方式 1、简介 开发中在MyBatis映射文件配置SQL语句&#xff0c;但是前面配置的都是比较简单的&#xff0c;不涉及稍复杂的业务场景。想要应…

SpringBootWeb案例 Part 5

4. 配置文件 员工管理的增删改查功能我们已开发完成&#xff0c;但在我们所开发的程序中还一些小问题&#xff0c;下面我们就来分析一下当前案例中存在的问题以及如何优化解决。 4.1 参数配置化 在我们之前编写的程序中进行文件上传时&#xff0c;需要调用AliOSSUtils工具类&…

STM32使用PID调速

STM32使用PID调速 PID原理 PID算法是一种闭环控制系统中常用的算法&#xff0c;它结合了比例&#xff08;P&#xff09;、积分&#xff08;I&#xff09;和微分&#xff08;D&#xff09;三个环节&#xff0c;以实现对系统的控制。它的目的是使 控制系统的输出值尽可能接近预…

Facebook HiPlot “让理解高维数据变得容易”

在这个全球信息化的时代&#xff0c;数据量呈爆炸式增长&#xff0c;数据的复杂性也是如此。如何有效地处理高维数据并找到隐藏在其中的相关性和模式是一个严峻的挑战。近年来&#xff0c;可视化和可视化分析已被应用于该任务&#xff0c;并取得了一些积极成果。Facebook的新Hi…

『C语言入门』初识C语言

文章目录 前言C语言简介一、Hello World&#xff01;1.1 编写代码1.2 代码解释1.3 编译和运行1.4 结果 二、数据类型2.1 基本数据类型2.2 复合数据类型2.3 指针类型2.4 枚举类型 三、C语言基础3.1 变量和常量3.2 运算符3.3 控制流语句3.4 注释单行注释多行注释注释的作用 四、 …

element表格多选实现

表格实现多选 实现表格多选很简单&#xff0c;只需要在表格里加上一列即可&#xff0c;加完之后就会在表格里出现一列白色的四方块按钮&#xff0c;可以多选&#xff0c;也可以单选 <el-table-columntype"selection"width"55"align"center"&…

iOS App逆向之:iOS应用砸壳技术

在iOS逆向&#xff0c;有一项关键的技术叫做“iOS砸壳”&#xff08;iOS App Decryption&#xff09;。自iOS 5版本以来&#xff0c;苹果引入了应用程序加密机制&#xff0c;使得大部分应用都需要进行砸壳操作才能进行逆向分析。因此作为开发者、逆向工程师和安全研究人员都需要…

Python Opencv实践 - 图像直方图自适应均衡化

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/cat.jpg", cv.IMREAD_GRAYSCALE) print(img.shape)#整幅图像做普通的直方图均衡化 img_hist_equalized cv.equalizeHist(img)#图像直方图自适应均衡化 #1. 创…

【动手学深度学习】--21.锚框

锚框 学习视频&#xff1a;锚框【动手学深度学习v2】 官方笔记&#xff1a;锚框 1.锚框 目标检测算法通常会在输入图像中采样大量的区域&#xff0c;然后判断这些区域中是否包含我们感兴趣的目标&#xff0c;并调整区域边界从而更准确地预测目标的真实边界框&#xff08;gro…

hive问题总结

往往用了很久的函数却只知道其单一的应用场景&#xff0c;本文将不断完善所遇到的好用的hive内置函数。 1.聚合函数或者求最大最小值函数搭配开窗函数使用可以实现滑动窗口 例&#xff1a; SELECT event,time,session_id,COLLECT_LIST(event) OVER (PARTITION BY session_id …

ChatGPT + Flutter快速开发多端聊天机器人App

下载地址&#xff1a;ChatGPT Flutter快速开发多端聊天机器人App 下载地址&#xff1a;ChatGPT Flutter快速开发多端聊天机器人App

PL 侧驱动和fpga 重加载的方法

可以解决很多的问题 时钟稳定后加载特定fpga ip &#xff08;要不内核崩的一塌糊涂&#xff09;fpga 稳定复位软件决定fpga ip 加载的时序 dluash load /usr/local/scripts/si5512_setup.lua usleep 30 mkdir -p /lib/firmware cp -rf /usr/local/firmare/{*.bit.bin,*.dtbo} …