C++性能优化篇:深拷贝、浅拷贝与移动构造

引言

最近在做性能优化,遇到了一个明显的性能问题,就是在大量数据做深拷贝的时候,程序耗时严重,几乎三分之一的时间都耗在了这里。于是乎仔细看了下此处的代码,发现这些深拷贝完全可以避免。

深拷贝、浅拷贝与移动构造

  • 浅拷贝 仅仅复制对象的数据成员的值,如果数据成员是指针,那么它会复制指针的值,而不是指针所指向的内容。这意味着两个对象会共享同一块内存区域。当其中一个对象修改了这块内存,另一个对象也会受到影响。如果没有特别定义拷贝构造函数或赋值操作符,编译器会自动生成默认的浅拷贝。
  • 深拷贝 深拷贝则不仅复制对象的数据成员,还会复制指针所指向的内容,即在堆上分配新的内存空间来存储被指针指向的数据。这样,即使两个对象有相同的指针成员,它们也会指向不同的内存区域,修改其中一个对象的指针所指向的数据不会影响另一个对象。深拷贝通常需要显式地实现拷贝构造函数和赋值操作符。
  • 移动构造 可以看出深拷贝和浅拷贝一般都发生在拷贝构造和赋值操作符中,虽然浅拷贝比深拷贝开销更小,但是其存在资源多次释放的问题。而移动构造可以避免这个问题,其实现方式通常是将源对象指针指向的资源转移到目标对象中,并将源对象的指针置为nullptr,以避免资源的重复释放。

代码优化

在了解了原理之后,就开始对我们的代码进行优化了。以下是优化前的示例代码:

class SampleData {
public:SampleData() {} // 默认构造函数// 带参构造函数SampleData(int size, int *data) {assert(data != nullptr);_size = size;_data = new int[_size];memcpy(_data, data, sizeof(int) * _size);}   SampleData(const SampleData& rhs) {_size = rhs._size;_data = new int[_size];memcpy(_data, rhs._data, sizeof(int) * _size);}SampleData& operator=(const SampleData& rhs) {_size = rhs._size;delete[] _data;_data = new int[_size];memcpy(_data, rhs._data, sizeof(int) * _size);return *this;}~SampleData() {_size = 0;delete[] _data;_data = nullptr;}void processData() {// do something}private:int _size{0};int* _data{nullptr};
};void func() {std::vector<SampleData> data_arr;int n = 100000;constexpr int size = 1000;int input_data[size] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};for (int i = 0; i < n; ++i) {SampleData data(size, input_data);data_arr.push_back(data); // 产生了深拷贝}
}int main()
{func();return 0;
}

优化之后,新增移动构造函数如下:

SampleData(SampleData&& rhs) {_size = rhs._size;_data = rhs._data;rhs._size = 0;rhs._data = nullptr;
}

func函数更改如下:

void func() {std::vector<SampleData> data_arr;int n = 100000;constexpr int size = 1000;int input_data[size] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};for (int i = 0; i < n; ++i) {SampleData data(size, input_data);data_arr.push_back(std::move(data)); // 移动构造}
}

总结

  • 在做性能优化的时候,遇到数据量较大的场景,减少不必要的数据拷贝,是可以极大得提高程序性能的。
  • 移动语义可以帮助我们实现在浅拷贝的同时,又能避免资源重复释放的问题。但是使用移动语义也要注意,被移动的对象在移动完成之后,不能再被使用,否则可能出现未知错误。

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

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

相关文章

Java实现RS485串口通信

博客链接地址 近期&#xff0c;我接到了一个任务&#xff0c;将报警器接入到Java项目中&#xff0c;而接入的方式就是通过RS485接入&#xff0c;本人之前可以说是对此毫无所知。不过要感谢现在的互联网&#xff0c;通过网络我查到了我想要知道的一切&#xff0c;这里记录下本次…

对数据分析行业的疑问

我之前是做大数据的开发的&#xff0c;当然也做业务比如Java、springcloud的后端开发、也做了ai的。 但是我一直没怎么做数据分析&#xff0c;当我加入了新公司后发现&#xff0c;现在做大数据的大部分都是数据分析&#xff0c;用python和sql。 我今天一看他们的统计&#xf…

STM32音频应用开发:DMA与定时器的高效协作

摘要: 本文章将深入浅出地介绍如何使用STM32单片机实现音频播放功能。文章将从音频基础知识入手&#xff0c;逐步讲解音频解码、DAC转换、音频放大等关键环节&#xff0c;并结合STM32 HAL库给出具体的代码实现和电路设计方案。最后&#xff0c;我们将通过一个实例演示如何播放W…

NXP RT1060学习总结 - fsl_flexcan CAN FD 函数说明 -1

概要 CAN测试源码&#xff1a; https://download.csdn.net/download/qq_35671135/89425377 根据fsl_flexcan.h文件从文件末尾往前面梳理&#xff0c;总共CAN FD处理函数&#xff1b; 使用的是RT1064开发板进行测试。 1、中止中断驱动的消息接收进程(CAN FD) 函 数 &#xf…

揭示优化Prompt的秘诀:如何让API表现媲美网页版

为什么用GPT API&#xff08;GPT-3.5-turbo&#xff09;进行程序分析时&#xff0c;效果好像比网页版的GPT-3.5差一点&#xff1f;这可能有几个原因&#xff0c;咱们细说一下。 1. Prompt不同 这是最常见的问题之一。API调用时的指令&#xff08;prompt&#xff09;往往比较简…

Ceil()——向上取整函数

函数原型为&#xff1a; double ceil(double x); 大家可以在这个网站里更清晰的了解ceil - C Reference (cplusplus.com) 下面借助一道例题来帮助大家理解&#xff1a;牛牛的快递_牛客题霸_牛客网 (nowcoder.com) 我们分析题得知&#xff0c;在大于1的情况下&#xff0c;只要…

学懂C#编程:常用高级技术——学会Lambda表达式的应用(二)

上一篇介绍了Lambda基础的知识&#xff0c;接着我们通过讲解Lambda的几种应用场景来彻底学懂Lambda在编程中的应用。 Lambda表达式在C#中非常灵活&#xff0c;可以用在多种场合。以下是一些Lambda表达式示例&#xff0c;帮助你更全面地理解其用途&#xff1a; 1. 数组过滤&am…

【ocean】ocnPrin结合getData导出数据

核心就是这一句ocnPrint(?output fout leafValue( getData(“/output” ?result “dc”))) r_list list(4000, 4100, 4200) multi_list list(20,21,22) fout outfile("/home/yourpath/results.txt" "w") foreach(r_value r_listforeach(multi_value …

【Linux基础命令】文件管理命令(二)

文章目录 前言创建删除目录创建目录删除目录cp命令mv命令查看文件内容总结前言 在我们的上一篇文章中,我们介绍了一些基本的Linux文件管理命令,如 cd、ls 等。这些命令对于日常的文件操作任务非常有用。然而,Linux 提供的功能远不止这些。在本文中,我们将继续探索更多的文…

【unity实战】制作unity数据保存和加载系统——大型游戏存储的最优解

最终效果 文章目录 最终效果前言存储位置信息存储更多数据存储场景信息持久化存储数据完结 前言 前面写过小型游戏存储功能&#xff1a; 【unity实战】制作unity数据保存和加载系统——小型游戏存储的最优解&#xff08;包含数据安全处理方案的加密解密&#xff09; 这次做一…

基于RK3568车载电脑助力日本巴士公司高效完成巴士到站系统项目部署

无处不在的物联网&#xff08;IoT&#xff09;技术已经渗透到了人类生活的各个角落&#xff0c;如日常出行乘坐的公交车上&#xff0c;物联网&#xff08;IoT&#xff09;技术的应用就得到完美诠释&#xff01;其通过公交车上的车载电脑网络与中控室服务器连接来对公交车的运行…

Vue-Ci搭建项目

项目创建 vue-cli 官方提供的一个脚手架,用于快速生成一个vue的项目模板;预先定义 好的目录结构及基础代码,就好比咱们在创建Maven项目时可以选择创建一个 骨架项目,这个骨架项目就是脚手架,我们的开发更加的快速; 主要的功能 ● 统一的目录结构 ● 本地调试 热部署 ● 单元…

Rust详解日志

详解日志 相比起监控&#xff0c;日志好理解的多&#xff1a;在某个时间点向指定的地方输出一条信息&#xff0c;里面记录着重要性、时间、地点和发生的事件&#xff0c;这就是日志。 注意&#xff0c;本文和 Rust 无关&#xff0c;我们争取从一个中立的角度去介绍何为日志 日…

低代码开发平台:人人都可以开发应用

低代码开发平台是一种快速应用开发工具&#xff0c;它允许用户通过图形界面和模型驱动逻辑来构建应用程序&#xff0c;而不需要编写大量的代码。这种平台的目的是简化开发流程&#xff0c;降低技术门槛&#xff0c;使得非专业开发者也能快速构建应用程序。 低代码开发的优势 低…

IBM Spectrum LSF Application Center 提供单一界面来管理应用程序、用户、资源和数据

IBM Spectrum LSF Application Center 提供单一界面来管理应用程序、用户、资源和数据 亮点 ● 简化应用程序管理 ● 提高您的工作效率 ● 降低资源管理的复杂性 ● 深入了解流程 IBM Spectrum LSF Application Center 为集群用户和管理员提供了一个灵活的、以应用为中心的界…

openwrt igmp 适配

每弄完一次&#xff0c;过不多久就忘了&#xff0c;这次决心记下来。 openwrt 的igmpproxy 包是干嘛的&#xff1f;原来&#xff0c;组播包并不能穿透路由&#xff0c;也就是我们在wan端播放的组播视频流&#xff0c;lan端是没法收到的&#xff0c;igmpproxy就是用来打通wan端…

2024.6.26 刷题总结

2024.6.26 **每日一题** 526.优美的排列&#xff0c;该题考察的是状压dp的知识&#xff0c;用一个n位的二进制数表示排列中的数被选取的情况&#xff0c;若为1&#xff0c;则表示该位被选取&#xff0c;若为0&#xff0c;则表示该位没有被选取&#xff0c;用一个数组来存储当前…

STM32F1+HAL库+FreeTOTS学习1——FreeRTOS入门

STM32F1HAL库FreeTOTS学习1——FreeRTOS入门 裸机开发与操作系统嵌入式操作系统简介FreeRTOS简介FreeRTOS的几个重要概念任务调度器任务状态状态列表 裸机开发与操作系统 在以往的嵌入式学习中&#xff0c;我们最常用的就是裸机开发&#xff0c;所谓裸机开发就是指在没有操作系…

力扣1541. 平衡括号字符串的最少插入次数

Problem: 1541. 平衡括号字符串的最少插入次数 文章目录 题目描述思路及解法复杂度Code 题目描述 思路及解法 Problem: 力扣921. 使括号有效的最少添加 类似于上述题目&#xff0c;不过此时一个左括号要和两个右括号配对 1.同理上述题目&#xff0c;遍历字符串时若遇见一个左括…

揭秘微生物社区的“社交网络”:基因组规模代谢模型(GEMs)的新前沿

当前&#xff0c;微生物群落的基因组组成和功能潜力通过宏基因组组装基因组&#xff08;MAGs&#xff09;的分析得以部分揭示&#xff0c;但其内在的代谢网络和相互作用机制仍充满未知。为此&#xff0c;科学家们开发了基因组规模的代谢模型&#xff08;GEMs&#xff09;&#…