C++ std::vector及使用时的常见优化策略

std::vector 是 C++ 标准模板库(STL)中的一个动态数组容器。它提供了动态大小调整和高效的随机访问功能,非常适合需要频繁插入、删除和访问元素的场景。std::vector 是在 <vector> 头文件中定义的,并且位于 std 命名空间中。

1. 特点

(1)动态大小调整:std::vector 可以根据需要自动调整其大小。
(2)连续内存存储:std::vector 内部使用连续内存存储元素,这意味着可以通过指针或索引高效地访问元素。
(3)高效的随机访问:支持常数时间的随机访问。
(4)自动管理内存:std::vector 自动管理其内部使用的内存,不需要手动分配和释放。
(5)支持常见容器操作:如插入、删除、遍历等。

2. 常用成员函数

2.1 迭代器

  • begin():返回指向第一个元素的迭代器。
  • end():返回指向最后一个元素之后的迭代器。
  • rbegin():返回指向最后一个元素的逆向迭代器。
  • rend():返回指向第一个元素之前的逆向迭代器。

2.2 容量

  • size():返回当前元素的数量。
  • capacity():返回当前分配的存储容量。
  • empty():检查容器是否为空。
  • reserve(size_type new_cap):请求分配至少能容纳 new_cap 个元素的存储空间。
  • shrink_to_fit():请求减少容量以适应当前大小。

2.3 元素访问

  • operator[]:访问指定位置的元素。
  • at(size_type pos):访问指定位置的元素,并进行越界检查。
  • front():访问第一个元素。
  • back():访问最后一个元素。
  • data():返回指向底层数组的指针。

2.4 修改器

  • push_back(const T& value):在末尾添加元素。
  • pop_back():删除末尾的元素。
  • insert(iterator pos, const T& value):在指定位置插入元素。
  • erase(iterator pos):删除指定位置的元素。
  • clear():清空所有元素。
  • resize(size_type count, T value = T()):调整容器大小。

示例代码

#include <iostream>
#include <vector>int main() {// 创建一个空的 vectorstd::vector<int> vec;// 添加元素vec.push_back(10);vec.push_back(20);vec.push_back(30);// 访问元素std::cout << "First element: " << vec[0] << std::endl;std::cout << "Second element: " << vec.at(1) << std::endl;std::cout << "Last element: " << vec.back() << std::endl;// 遍历元素std::cout << "Elements: ";for (const int& elem : vec) {std::cout << elem << " ";}std::cout << std::endl;// 在第二个位置插入值为15的元素vec.insert(vec.begin() + 1, 15);// 删除第三个元素vec.erase(vec.begin() + 2);// 重新遍历std::cout << "Modified elements: ";for (const int& elem : vec) {std::cout << elem << " ";}std::cout << std::endl;// 调整大小,并将扩展的元素初始化为100vec.resize(5, 100);// 重新遍历std::cout << "Resized elements: ";for (const int& elem : vec) {std::cout << elem << " ";}std::cout << std::endl;return 0;
}

3. 常见优化策略

在使用 std::vector 时,有一些常见的优化策略可以帮助你提高性能和效率。以下是一些优化建议:

3.1 预分配内存

使用 reserve 方法预分配内存可以减少内存重新分配的次数,从而提高性能。特别是在知道大概需要多少元素时,这非常有用。

#include <vector>int main() {std::vector<int> vec;vec.reserve(1000); // 预分配足够的内存for (int i = 0; i < 1000; ++i) {vec.push_back(i);}return 0;
}

3.2 避免不必要的拷贝

在传递 std::vector 时,尽量使用引用(const 引用)来避免不必要的拷贝。

#include <vector>// 使用 const 引用来避免拷贝
void processVector(const std::vector<int>& vec) {// 处理 vector
}int main() {std::vector<int> vec = {1, 2, 3, 4, 5};processVector(vec);return 0;
}

3.3 使用 emplace_back 而不是 push_back

emplace_back 可以直接在容器内构造元素,避免了额外的拷贝或移动操作。

#include <vector>struct MyStruct {int x;MyStruct(int val) : x(val) {}
};int main() {std::vector<MyStruct> vec;vec.reserve(10); // 预分配内存vec.emplace_back(1); // 直接在容器内构造元素vec.emplace_back(2);return 0;
}

3.4 使用 shrink_to_fit 释放多余内存

在删除大量元素后,可以使用 shrink_to_fit 来释放多余的内存。

#include <vector>int main() {std::vector<int> vec(1000, 1);vec.erase(vec.begin(), vec.end() - 500); // 删除前 500 个元素vec.shrink_to_fit(); // 释放多余的内存return 0;
}

3.5 避免频繁的插入和删除操作

尽量避免在 std::vector 中间进行频繁的插入和删除操作,因为这会导致大量的元素移动。可以考虑使用其他适合频繁插入和删除的容器,如 std::list std::deque

3.6 使用合适的迭代器

使用迭代器来遍历 std::vector ,避免使用索引访问,尤其是在大型 vector 中,这样可以提高代码的可读性和性能。

#include <vector>
#include <iostream>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};// 使用迭代器遍历 vectorfor (auto it = vec.begin(); it != vec.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}

3.7 使用算法库

使用标准库中的算法,如 std::sortstd::find 等,可以提高代码的效率和可读性。

#include <vector>
#include <algorithm>
#include <iostream>int main() {std::vector<int> vec = {5, 3, 1, 4, 2};std::sort(vec.begin(), vec.end()); // 使用标准库算法排序for (const int& elem : vec) {std::cout << elem << " ";}std::cout << std::endl;return 0;
}

3.8 避免多次调用 size() 函数

在循环中多次调用 size() 函数可能会影响性能,尤其是在一些复杂的容器中。可以将 size() 的结果存储在一个变量中,然后在循环中使用这个变量。

#include <vector>
#include <iostream>int main() {std::vector<int> vec = {1, 2, 3, 4, 5};size_t size = vec.size(); // 将 size() 的结果存储在变量中for (size_t i = 0; i < size; ++i) {std::cout << vec[i] << " ";}std::cout << std::endl;return 0;
}

总结
std::vector 是一个强大且灵活的容器,适用于需要动态调整大小、频繁插入和删除操作的场景。它提供了丰富的成员函数和操作,能够满足大多数常见的使用需求。通过理解和掌握 std::vector ,可以大大提高 C++ 编程的效率和代码的可读性。

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

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

相关文章

案例实践 | 基于长安链的福建省气象综合治理区块链平台

案例名称-【福建省气象综合治理区块链平台】 ■ 实施单位 福建福链科技有限公司 ■ 业主单位 福建省气象信息中心 ■ 上线时间 2023年10月 ■ 用户群体 福建省气象、防灾减灾相关单位 ■ 用户规模 全省2100余个气象站、气象局以及防灾减灾部门 案例背景与解决痛点 …

跟代码执行流程,读Megatron源码(四)megatron初始化脚本initialize.py之initialize_megatron()分布式环境初始化

在前文中&#xff0c;我们讲述了pretrain函数的执行流程&#xff0c;其首要步骤是megatron分组的初始化与环境的配置。本文将深入initialize_megatron函数源码&#xff0c;剖析其初始化分布式训练环境的内部机制。 注&#xff1a;在此假设读者具备3D并行相关知识 一. initiali…

【MARL】MADDPG + attention 实现(+论文解读)

文章目录 前言注意力机制论文里的attention回顾知识-MADDPG讲解1.Q的定义2.Q的恒等式3.论文里的attention4.好处 实现 和 修改结果展示原论文代码 翻改版修改后原maddpg代码 前言 导师让在MADDPG上加一个注意力机制&#xff0c;试了很多种&#xff0c;下面的参考的论文的效果最…

C++——保持原有库头文件不变的情况下,成功编译运行工程

问&#xff1a;想要保持原来库方式&#xff0c;应该怎么操作呢&#xff1f; 答&#xff1a;如果想保持原来的方式&#xff0c;则只需要将 库所在路径 tracker/detector/rknn_model_zoo/utils 加入到 工程库包含中即可。

基于jeecgboot-vue3的Flowable流程-自定义业务表单流程历史信息显示

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 1、对于自定义业务表单的流程历史记录信息做了调整&#xff0c;增加显示自定义业务表单 <el-tab-pane label"表单信息" name"form"><div v-if"customF…

ESP32开发进阶:OLED屏幕显示旋转的3D模型

一、硬件接线 我选择的是最常见的一块板子&#xff1a;ESP-WROOM-32&#xff0c;硬件接线如下&#xff1a; 21 - SDA 22 - SCL 二、Arduino端代码 我们使用Arduino和Adafruit SSD1306库在OLED显示屏上绘制和旋转一个3D立方体。 首先&#xff0c;定义立方体顶点和…

国际金融入门:国际收支与平衡表解析

在全球化的经济体系中&#xff0c;国际金融已成为我们日常生活不可或缺的一部分。了解国际金融的基础知识&#xff0c;可以帮助我们更好地理解世界经济的动态和趋势。今天&#xff0c;我们将深入探讨国际收支及其平衡表&#xff0c;以及它们是如何影响国家经济。 国际收支&…

2024.07-电视版免费影视App推荐和猫影视catvod、TVBox源(最新接口地址)

文章目录 电视版免费影视App推荐精选列表&#xff08;2024.07可用筛选列表&#xff09;&#xff1a;2024.07可用筛选列表&#xff0c;盲盒资源打包合集下载安装说明真的是盲盒&#xff1f; 猫影视catvod、TVBoxTVBox源推荐可用列表目前不可用列表&#xff08;前缀为错误状态码&…

探索 Odoo 前端源码

今天我们要深入探索一段 Odoo 前端源码。这段代码看似简单,却隐藏着 Odoo 应用高效运行的秘密。我们一起来解读这段源码,了解它在 Odoo 中的作用,并教你如何正确使用它。准备好了吗?让我们开始这段奇妙之旅吧! /** @odoo-module **/import { registry } from "./cor…

CSS(七)——CSS 列表和CSS Table(表格)

目录 CSS 列表 列表 作为列表项标记的图像 列表 - 简写属性 移除默认设置 所有的CSS列表属性 CSS 表格 表格边框 折叠边框&#xff08;border-collapse&#xff09; 表格宽度和高度 表格文字对齐 表格填充 表格颜色 CSS 列表 CSS 列表属性作用如下&#xff1a; 设…

mysql 主从复制 读写分离 MHA

mysql 的主从复制和读写分离&#xff1a; 读写分离和MHA高可用的前提 主从复制 主从复制的模式&#xff1a; 1.mysql的默认模式 异步模式&#xff1a;主库在更新完事务之后会立即把结果返回给从服务器&#xff0c;不关心从库是否接收到&#xff0c;是否处理成功 网络问题可能…

大模型学习应用 1:用 itrex 创新高效实现 LLM 的部署和微调

用 itrex 创新高效实现 LLM 的部署和微调 - 项目作业 目录 准备工作Task 1 完成在线环境的工具包安装&#xff0c;包含 基础环境包、Extension for Transformers 包、加速计算包Task 2 利用 Intel Extension for Transformers 部署通义千问 Qwen-7B Chat&#xff0c;并根据 pr…

zynqmpsoc On-chip Memory

zynqmpsoc 开发手册 On-chip Memory 章节 Introduction The on-chip memory (OCM) contains 256 KB of RAM. It supports a 128-bit AXI slave interface port. The OCM has eight exclusive access monitors that can simultaneously monitor up to eight exclusive access tr…

前端系列-7 Vue3响应式数据

1.响应式数据和实现 响应式数据的核心是当数据模型发生变化时&#xff0c;与之相关(使用该数据模型)的视图或组件可以自动更新&#xff0c;以反映最新的数据状态。 实现原理是数据劫持、依赖收集和分发更新&#xff0c;数据劫持是一种AOP策略。 在vue2中通过Object.defineProp…

(四)js前端开发中设计模式之简单工厂模式

简单工厂模式,又叫静态工厂方法&#xff0c;由一个工厂对象决定创建出哪一种产品类的实例&#xff0c;主要用来创建同一类对象 let LoginAlert function (msg) {this.content msg } LoginAlert.prototype {show() {const div document.createElement(div)div.style.cssText…

C#开发的全屏图片切换效果应用 - 开源研究系列文章 - 个人小作品

这天无聊&#xff0c;想到上次开发的图片显示软件《 PhotoNet看图软件 》&#xff0c;然后想到开发一个全屏图片切换效果的应用&#xff0c;类似于屏幕保护程序&#xff0c;于是就写了此博文。这个应用比较简单&#xff0c;主要是全屏切换换图片效果的问题。 1、 项目目录&…

设计模式实战:文件系统的设计与实现

问题描述 设计一个文件系统模拟器,用户可以创建文件和文件夹,对文件进行复制、删除等操作,并支持克隆文件和文件夹。系统需要实现组合模式来处理文件和文件夹的层次结构,使用命令模式来封装操作,并利用原型模式实现文件和文件夹的克隆。 设计分析 组合模式 组合模式用…

自动驾驶-机器人-slam-定位面经和面试知识系列04之高频面试题(02)

这个博客系列会分为C STL-面经、常考公式推导和SLAM面经面试题等三个系列进行更新&#xff0c;基本涵盖了自己秋招历程被问过的面试内容&#xff08;除了实习和学校项目相关的具体细节&#xff09;。在知乎和牛客&#xff08;牛客上某些文章上会附上内推码&#xff09;也会同步…

【Vue3】watch 监视 ref 定义的数据

【Vue3】watch 监视 ref 定义的数据 背景简介开发环境开发步骤及源码参数说明 背景 随着年龄的增长&#xff0c;很多曾经烂熟于心的技术原理已被岁月摩擦得愈发模糊起来&#xff0c;技术出身的人总是很难放下一些执念&#xff0c;遂将这些知识整理成文&#xff0c;以纪念曾经努…

【C++进阶学习】第八弹——红黑树的原理与实现——探讨树形结构存储的最优解

二叉搜索树&#xff1a;【C进阶学习】第五弹——二叉搜索树——二叉树进阶及set和map的铺垫-CSDN博客 AVL树&#xff1a; ​​​​​​【C进阶学习】第七弹——AVL树——树形结构存储数据的经典模块-CSDN博客 前言&#xff1a; 在前面&#xff0c;我们已经学习了二叉搜索树和…