C++的vector使用优化

我们在上一章说了如何使用这个vector动态数组,这章我们说说如何更好的使用它以及它是如何工作的。当你创建一个vector,然后使用push_back添加元素,当当前的vector的内存不够时,会从内存中的旧位置复制到内存中的新位置,然后删除删除旧位置的内存,也就是说当我push_back,vector容量不够添加元素就会调整大小,重新分配,这也就是将代码拖慢的原因之一。是事实,我们需要不断的重新分配,这是一个非常缓慢的操作,应该避免。我们如何避免复制对象,如果我们处理的是vector,特别是基于vector的对象,我们没有存储vector指针,我们存储的是vector对象,那占的内存就更大了,所以我们要优化复制。

#include <iostream>
#include <string>
#include <vector>struct Vertex
{float x, y, z;Vertex(float x, float y, float z): x(x), y(y), z(z){}//拷贝构造Vertex(const Vertex& vertex): x(vertex.x), y(vertex.y), z(vertex.z){std::cout << "Copied!" << std::endl;}
};int main()
{std::vector<Vertex> vertices;//打印6次//vertices.push_back(Vertex(1, 2, 3));//vertices.push_back(Vertex(4, 8, 9));//vertices.push_back(Vertex(7, 5, 6));//打印3次vertices.reserve(3);vertices.push_back(Vertex(1, 2, 3));vertices.push_back(Vertex(4, 8, 9));vertices.push_back(Vertex(7, 5, 6));std::cin.get();//打印0次vertices.emplace_back(1, 2, 3);vertices.emplace_back(14, 4, 6);vertices.emplace_back(7, 8, 9);}

在上面这段代码中,我们复制了6次(调用了6次拷贝构造函数),这个是为什么呢?当我们在push_back的时候,我们实际是在,主函数的当前帧中构造它,所以我们在main的栈上创建它,然后我们需要做的是,把它放到这个vector中,所以我们是从main函数中(把这个创建的vertex)放到实际的vector中。

在 C++ 中,std::vector 是一个动态数组,它可以调整其大小以容纳不同数量的元素。当你调用 reserve 方法时,你告诉 vector 它应该预先分配足够的内存来存储指定数量的元素,但并不会真正添加这些元素。这样做的好处是,当你稍后添加元素到 vector 时,它可能不需要重新分配内存(如果添加的元素数量没有超过预留的数量),这可以提高效率,因为内存分配通常是一个昂贵的操作。

在我们的代码中,由于预留了 3 个元素的空间,因此当你添加前三个元素时,不需要重新分配内存,所以不会调用拷贝构造函数(除了可能的隐式移动构造函数或复制省略,但这些在这个例子中都不适用,因为直接传递了临时对象)。但是,如果你没有调用 reserve,并且 vector 的初始容量小于你要添加的元素数量,那么在添加元素时可能需要重新分配内存。在重新分配内存时,旧的元素会被拷贝(或移动)到新的内存位置,这就会调用拷贝构造函数(或移动构造函数)。

当你使用 vertices.emplace_back(1, 2, 3);(以及类似的 emplace_back 调用)时,你实际上是在告诉 std::vector 直接在其内部存储中构造 Vertex 对象,而不是先创建一个临时对象然后再将其拷贝或移动到 vector 中。这是 emplace_back 相较于 push_back 的主要优势之一,因为它避免了不必要的拷贝或移动操作,从而提高了效率。

由于 emplace_back 直接在 vector 的内存中构造对象,它不会调用 Vertex 的拷贝构造函数。相反,它会调用 Vertex 的构造函数,直接传递参数给构造函数来构造对象。这就是为什么你在使用 emplace_back 后没有看到 "Copied!" 的输出。而是三次Constructed!

#include <iostream>
#include <string>
#include <vector>struct Vertex
{float x, y, z;Vertex(float x, float y, float z): x(x), y(y), z(z){std::cout << "Constructed!" << std::endl;}//拷贝构造Vertex(const Vertex& vertex): x(vertex.x), y(vertex.y), z(vertex.z){std::cout << "Copied!" << std::endl;}
};int main()
{std::vector<Vertex> vertices;vertices.reserve(3);vertices.emplace_back(1, 2, 3);vertices.emplace_back(14, 4, 6);vertices.emplace_back(7, 8, 9);std::cin.get();
}

运行上述代码,你会看到 "Constructed!" 被打印了3次,而不是 "Copied!",因为 emplace_back 直接在 vector 的内存中构造了 Vertex 对象。 

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

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

相关文章

Spring 之 Lifecycle 及 SmartLifecycle

最近在看Eureka源码&#xff0c;本想快速解决这场没有硝烟的战役&#xff0c;不曾想阻塞性问题一个接一个。为正确理解这个框架&#xff0c;我不得不耐着性子&#xff0c;慢慢梳理这些让人困惑的点。譬如本章要梳理的Lifecycle和SmartLifecycle。它们均为接口&#xff0c;其中后…

mysql的锁(全局锁)

文章目录 mysql按照锁的粒度分类全局锁概念&#xff1a;全局锁使用场景&#xff1a;全局锁备份案例&#xff1a; mysql按照锁的粒度分类 全局锁 概念&#xff1a; 全局锁就是对整个数据库实例加锁。MySQL 提供了一个加全局读锁的方法&#xff0c;命令是: Flush tables with…

java —— 文件的创建、删除、查询和重命名

文件的相关操作通过 File 类并引入路径来实现&#xff0c;这里对文件的操作只是对文件本身的增、删、查等&#xff0c;不包括对文件内容的修改。 一、创建文件/文件夹 public static void main(String[] args) {//创建文件File file1new File("D:\\android\\test\\a.jpg…

vue封装url验证方法

vue封装url验证方法 在 Vue 中&#xff0c;你可以封装一个 URL 验证的方法来验证给定的 URL 是否有效。以下是一个示例代码&#xff1a; export const validateUrl (url) > {const regex /^(https?:\/\/)?([\da-z.-])\.([a-z.]{2,6})([/\w .-]*)*/;return regex.test(…

排序算法——归并排序以及非递归实现

一、归并排序思想 归并排序&#xff08;MERGE-SORT&#xff09;是建立在归并操作上的一种有效的排序算法,该算法是采用分治法&#xff08;Divide andConquer&#xff09;的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个子序列…

OkHttp,一个贼牛的Java工具包

在当今的网络应用开发中,Java 作为一种成熟的编程语言,广泛应用于服务器端和客户端的开发。网络请求作为应用开发中不可或缺的一部分,选择一个高效、稳定的网络库尤为重要。OkHttp 就是这样一款优秀的网络库,它为Java提供了简单易用、功能强大的网络请求能力。本文将向读者…

关于编译的一些思路和猜想

一、编译原理的难度 编译原理特别复杂&#xff0c;研究的是高级语言如何翻译成汇编语言的过程。 二、编译过程中一些思路 (一)语义识别的作用 语义识别指的是把一些无关字符忽略&#xff0c;把一些变量名保存在一起&#xff0c;把用空格隔开的关键字单独放一起。 例如&#…

重新ysyx

一、克隆仓库 1.创建ssh key ssh-keygen -t rsa cd ~/.ssh ls 查看里面是否有id_rsa id_rsa.pub ssh-keygen -t rsa -C "xiantong15834753336outlook.com" cat id_rsa.pub***********查看里面的内容&#xff0c;复制到下图中绿色的按钮 git init ssh -T g…

spark3.0.1版本查询Hbase数据库例子

需求背景 现有需求&#xff0c;需要采用spark查询hbase数据库的数据同步到中间分析库&#xff0c;记录spark集成hbase的简单例子代码 import org.apache.hadoop.hbase.HBaseConfiguration import org.apache.hadoop.hbase.client.{ConnectionFactory, Scan} import org.apach…

Marin说PCB之Max parallel知多少?

今天是个阳光明媚&#xff0c;万里乌云的好日子。小编我一如既往地到家打开电脑准备看腾讯视频的五十公里桃花坞的第四季&#xff0c;在看到汪苏泷汪台说650电台要解散的时候小编我差点也哭了。650电台之于桃花坞就像乐队的鼓手一样&#xff0c;都是一个团队的灵感啊&#xff0…

CSS中的长度单位详解

在CSS中&#xff0c;长度单位是定义元素尺寸、间距、边距等的重要工具。不同的长度单位具有不同的特性和使用场景。 绝对长度单位 绝对长度单位在所有设备和浏览器中表示相同的长度。这些单位包括&#xff1a; 1.像素&#xff08;px&#xff09; 像素是最常用的长度单位。一…

C语言分支和循环(2)

我的相关博客&#xff1a; C语言的分支与循环&#xff08;1&#xff09; 1.switch语句 除了 if 语句外&#xff0c;C语⾔还提供了 switch 语句来实现分⽀结构。 switch 语句是⼀种特殊形式的 的 if...else 结构&#xff0c;⽤于判断条件有多个结果的情况。它把多重 else if…

非质量成本总结

非质量成本 非质量成本 定义 举例 固定成本 不随生产量或工作量变动而变动的成本 办公室租赁费 可变成本 随着生产量或工作变动而变动的成本 材料费 直接成本 可以直接计入某项目的成本 工人工资 间接成本 不能直接计入某项目而需要再几个项目之间或在项目与职能部…

Linux基本指令3

Linux基本指令3 目录 Linux基本指令3 一、Linux文件系统管理 二、Linux进程与服务管理

亿发:制造型企业信息化规划——从破冰到全面落地

在制造型企业中&#xff0c;信息化规划的落地是一个复杂而关键的过程。尽管规划和蓝图可能已经制定完毕&#xff0c;但如何成功地实施信息化才是关键所在。本文将详细介绍制造型企业信息化规划的落地过程&#xff0c;通过三个周期逐步推进&#xff0c;最终实现信息化与自动化的…

深度学习知识与心得

目录 深度学习简介 传统机器学习 深度学习发展 感知机 前馈神经网络 前馈神经网络&#xff08;BP网络&#xff09; 深度学习框架讲解 深度学习框架 TensorFlow 一个简单的线性函数拟合过程 卷积神经网络CNN&#xff08;计算机视觉&#xff09; 自然语言处理NLP Wo…

OpenAI助手API接入-问答对自动生成

支持GPT-3.5-Turbo, GPT-4o, GPT-4-Turbo import json import openai from pathlib import Path import os client openai.OpenAI(base_urlbase_url, api_keyapi_key) file client.files.create( fileopen("H3.pdf", "rb"), purposeassistants ) …

HTTP 的三次握手

​​​​​ HTTP 的三次握手是指在建立 TCP 连接时&#xff0c;客户端和服务器之间进行的三步握手过程。这个过程确保了双方都能够互相通信&#xff0c;并且同步了彼此的序列号和确认号。 概念&#xff1a; 第一次握手&#xff1a;客户端发送一个 SYN&#xff08;同步…

2.1数据的表示和运算--进位制

2.数据的表示和运算 2.1进位制 &#x1f53a;问题&#xff1a;计算机采用二进制有什么优点&#xff1f; 答&#xff1a; 1.制造两个稳态的物理器件较容易。 2.二进制的运算规则简单。 3.便于用逻辑门电路实现运算。 4.二进制的0和1正好对应逻辑值真和假。 &#x1f53a;…

成功解决“ModuleNotFoundError: No Module Named ‘utils’”错误的全面指南

成功解决“ModuleNotFoundError: No Module Named ‘utils’”错误的全面指南 在Python编程中&#xff0c;遇到ModuleNotFoundError: No Module Named utils这样的错误通常意味着Python解释器无法找到名为utils的模块。这可能是由于多种原因造成的&#xff0c;比如模块确实不存…