C++ 数据结构之std::vector介绍

【C++基础】std::vector详解 是 C++ 标准库中的一个容器,提供了动态数组的功能。它的底层实现通常是使用连续的内存块来存储元素,因此可以通过指针算术来访问元素,并且支持常数时间的随机访问,并支持在容器末尾高效地添加和删除元素。 阅读详情

std::vector与数组类似,但它更加智能,能自动管理内存大小。

假设你要处理用户上传的Excel数据,行数可能从几十到几万行不等——这时用固定大小的数组会捉襟见肘,而使用std::vector就能游刃有余。

关键特性速览

  • 动态伸缩:容量不够时自动扩容
  • 快速访问:通过下标直接访问元素,时间复杂度O(1)
  • 内存连续:数据在内存中紧密排列,这对缓存机制非常友好

核心操作

基础三板斧

#include <iostream>
#include <vector>

int main() {
    // 创建与初始化
    std::vector<int> primes = {0, 1, 2, 3, 4, 5, 6};  // 直接初始化
    std::vector<std::string> names;                   // 空容器

    // 增删元素
    primes.push_back(7);      // 尾部追加
    primes.pop_back();        // 删除末尾

    // 随机访问
    std::cout << primes[0] << std::endl;        // 输出0(不检查越界)
    std::cout << primes.at(6) << std::endl;     // 输出6(越界会抛出异常)
}

进阶操作

当需要处理游戏中的动态对象时,可以这样操作:

#include <iostream>
#include <vector>
#include <algorithm>

struct Enemy {
    std::string name;
    int health;
    Enemy(std::string name_, int health_) {
        name = name_;
        health = health_;
    }
};

int main() {
    
    std::vector<Enemy> enemies;
    // 新敌人出现
    enemies.emplace_back("Zombie_0", 80); // 直接构造更高效
    enemies.emplace_back("Zombie_1", 90);
    enemies.emplace_back("Zombie_2", 100);

    // 击杀敌人
    enemies[0].health = 0;
    enemies[2].health = 0;

    // 处理阵亡敌人 (注意erase-remove惯用法)
    auto it = remove_if(enemies.begin(), enemies.end(), 
    [](const Enemy& e) { return e.health <= 0; });
     
    enemies.erase(it, enemies.end());
    
    return 0;
}

性能优化

1. 预分配空间

当知道大概元素数量时,提前预留空间:

std::vector<SensorData> data;
data.reserve(5000);  // 避免插入时的多次扩容

2. 选择正确的构造方式

// 传统方式:先构造再拷贝
objects.push_back(MyClass(param1, param2)); 

// 优化方式:原地构造
objects.emplace_back(param1, param2);  // 省去临时对象拷贝

3. 高效删除技巧

需要删除中间元素时,如果不在乎顺序,可以交换位置后删除末尾:

std::swap(v[index], v.back());  // 把要删的元素换到最后
v.pop_back();                   // 此时删除成本最低

如果需要保持顺序,那么可以使用erase:

v.erase(v.begin() + index);

4. 利用现代C++特性

移动语义能大幅提升效率:

std::vector<std::string> buffer;
std::string large_data = fetch_data();  // 假设这是个很大的字符串
buffer.push_back(std::move(large_data)); // 转移所有权而非复制

避坑指南

误区1:盲目使用[]操作符

std::vector<int> v = {1, 2, 3};
std:cout << v[5] << std::endl;  // 越界访问!

建议在不确定时使用at()方法,虽然慢一点但安全:

try {
    std::cout << v.at(5) << std::endl;  // 会抛出out_of_range异常
} catch(const std::exception& e) {
    std::cerr << "访问越界:" << e.what() << std::endl;
}

误区2:在循环中反复扩容

// 低效写法
std::vector<Matrix> matrices;
for(int i = 0; i < 10000; i++) {
    matrices.push_back(create_matrix());  // 可能多次触发扩容
}

// 优化写法
matrices.reserve(10000);  // 一次性预留空间
for(int i = 0; i < 10000; i++) {
    matrices.push_back(create_matrix());
}

误区3:忽视迭代器失效问题

std::vector<int> nums = {1, 2, 3, 4, 5};
auto it = nums.begin();
while(it != nums.end()) {
    if(*it % 2 == 0){
        nums.erase(it);  // 错误!erase后迭代器失效
        // 应该用 it = nums.erase(it);
    } else {
        it++;
    }
}

总结

对于std::vector的介绍就到这里了,下次遇到需要动态数组的时候,不妨先考虑它,再根据具体需求调整策略。

希望本文对你有帮助!
本文首发于微信公众号《Linux在秋名山》,欢迎大家关注~

C++中常用的数据结构 一直以来虽然写的都是C++的代码但是基本上用的都是C的数据结构。这次实现一个相对大型的C++项目,发现了很多很有用的数据结构,通过使用这些数据结构,可以极大程度的提高开发效率。所以计划逐渐整理下C++的数据结构,以及他们的用法,以供自己以及小白参考。暂时不涉及时间性能。 std::string std::vector std::vector<int> vec; std::vector<int> vec(3); // 深度为3的整形数据 std::vector<int> 阅读详情

相关推荐

GNSS数据处理(一)——开源软件RTKLIB与G-Nut/Anubis实战入门

本文详细介绍了GNSS数据处理的开源软件RTKLIB与G-Nut/Anubis的实战入门指南。从软件安装、数据获取到静态短基线解算,逐步讲解操作技巧与常见问题排查,帮助测绘与地质监测人员快速掌握GNSS数据处理技术,提升工作效率。

weixin_30733003的博客 133

容器库——std::vector

容器库——std::vector详解

qq_44778120的博客 1万+

软件项目成本控制实战:从COCOMO模型到挣值分析的5个关键步骤

本文详细介绍了软件项目成本控制的5个关键步骤,从COCOMO模型估算到挣值分析预警,帮助中小型团队精准管理预算。通过简化COCOMO II的有机模式、动态建立成本基准、轻量化挣值分析等方法,项目经理可以有效应对预算超支和进度延误问题,提升项目成功率。

weixin_30733003的博客 227

C++ 中的 std::vector:动态数组操作和常用函数解析

C++ 中的 std::vector 是一个非常实用的容器,它提供了动态大小的数组功能,可以存储任意类型的元素,并且可以方便地进行元素的添加、删除和查询操作。本博客不仅介绍了一些常用的成员函数和操作符,如 push_back()、pop_back()、size()、empty() 和 clear(),还详细对比了 push_back() 和 emplace_back() 之间的区别。此外,博客还提供了一些小示例程序,以帮助读者更好地理解这些概念。

南城小馆 6972

PMF5.0计算

EPA PMF5.0 计算步骤

nuistsy的博客 4531

源码编译部署篇(二)源码编译milvus成功后如何启动standalone并调试成功!

由于Milvus官方文档只提及如何使用docker安装部署Milvus,关于源码安装方式篇幅较少,因此,我整理撰写了如何通过源码编译方式成功安装Milvus,详见此篇。之所以选择这种复杂的安装方式,可以调试源码进而熟悉Milvus如何搭建整个框架支持AI上层应用功能。根据上篇步骤部署虽然可以成功,然而,我却不能成功启动Milvus服务,这个问题困扰了一两天,现在终于得以解决并能成功调试Milvus源码。接下来,分为三个部分介绍如何启动和成功调试。

qq_43893755的博客 3367

vector与iterator的一些用法

  使用vector,要添加其头文件#include<vector>。   1.vector的初始化及赋值,比如:   std::vector<int> nVec;     // 空对象   std::vector<int> nVec(5,-1);  // 创建了一个包含5个元素且值为-1的vector   std::vector<std...

all36426的博客 1585

【WRFDA教程第四期】雷达数据同化(Radar Data Assimilation)

雷达数据同化(Radar Data Assimilation)

WW、forever的博客 1758

std : : vector

的底层实现通常基于,它是一种连续分配的内存块,允许元素的快速随机访问。下面是内部使用一块连续的内存块来存储其元素,这使得元素的随机访问非常高效,因为可以通过来访问元素。。当元素数量达到内部分配的容量时,会重新分配更大的内存块,并将元素复制到新的内存块中。这种自动内存管理使得向量的大小可以根据需要进行调整,而不需要手动管理内存。有两个重要的属性,即容量(capacity)和大小(size)。使用new和delete运算符(或malloc和free函数,取决于具体实现)来动态分配和释放内存。

Ricardo的博客 2770

buildozer

/home/chenyang/new_kivy/.buildozer/android/platform/build/build/other_builds/hostpython3/desktop/hostpython3/Lib

东方佑 16万+

第3讲:单端传输线的时域TDR仿真(基于实战的第一次仿真视角切换)

本文为CST仿真系列教程的第3讲,主要介绍传输线阻抗(TDR)的两种仿真方法:基于S参数的频域计算和基于高斯脉冲的时域计算。文章详细演示了在CST PCB Studio中修改电容参数、设置TDR仿真参数(包括截止时间和采样点数)的操作步骤,并通过对比实验展示TVS寄生电容对阻抗曲线的影响。最后将两种TDR方法的结果进行对比,验证了两种方法的一致性。本教程适合硬件工程师通过时域波形直观分析传输线阻抗特性,是信号完整性分析的重要技能。

一只豌豆象的博客 226

C++中std::vector容器的入门讲解

本文介绍了 std::vector 的用法。 std::vector 是 C++ 标准库中的一个容器,用于存储一组具有相同类型的元素。 std::vector ​​​​​​​具有动态分配内存、随机访问、尾部添加和删除元素等特性,是C++中常用的数据结构之一。

qq_50635297的博客 3322

Qt入门教程【基础控件篇】QLineEdit输入框

QLineEdit输入框

小鱼酱的博客 3261

C++高频交易数据结构选择:为何std::vector完胜std::list?

掌握C++高频交易开发技巧,揭秘为何std::vector在低延迟场景远超std::list。基于缓存友好访问、内存连续性与预分配优势,提升数据处理效率。适用行情解析与订单管理,值得收藏。

VarChat的博客 301

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

std::string std::vector std::map 源代码 结构

// vector standard header#pragma once #ifndef _VECTOR_ #define _VECTOR_ #ifndef RC_INVOKED #include &lt;memory&gt; #include &lt;stdexcept&gt; #include &lt;xfunctional&gt; #pragma pack(push,_CRT_PACK...

lacoucou的专栏 2180

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

Learn C++学习笔记:第六章— void指针、std::vector和std::array

void 指针 有void类型的函数,同理,也可以有void类型的指针。 void类型的指针可以指向任意类型数据,示例: int nValue; float fValue; struct Something { int n; float f; }; Something sValue; void *ptr; ptr = &nValue; // ok ptr =...

weixin_39548859的博客 1479

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

C++和标准库速成(五)——C风格的数组、std::array、std::vector、std::pair和std::optional

C风格数组、std::array、std::vector、std::pair和std::optional

qq_51180928的博客 1296

std::vector<std::vector<float>>概述及应用举例

std::vector概述及应用举例

xie__jin__cheng的博客 1465

C++ 的 vector 类

std::vector 是一个功能强大且灵活的容器,适合存储和管理动态大小的数组。它的简单易用和高效性能使其成为 C++ 中最常用的数据结构之一。通过理解和掌握 std::vector,你可以更高效地处理数据集合。

qq_41349978的博客 610

C++ string和vector

在C++中,是一个表示文本字符串的类。它封装了字符数组的处理,提供了丰富的成员函数,用于执行各种字符串操作,如连接、查找、比较、替换等。类定义在标准库头文件中,是标准模板库(STL)的一部分。

m0_73640344的博客 2302

C++数据结构【顺序表和Vector】

int *a;// 指向动态申请的数组的地址// 标记当前数组的容量(能存储的元素总数)int n;// 标记当前有效元素的个数// 查找x在数组中最后出现的下标// 初始化为无效值++i) {// 不断更新为最新匹配的下标// 测试示例= -1) {std::cout << target << "最后出现的下标:" << lastPos << std::endl;// 输出:5} else {std::cout << "未找到" << target << std::endl;

2403_87559458的博客 978

深入解析C++标准库中的std::list容器

在 C++ 中是一个双向链表(doubly linked list)。这是一个链式数据结构,其中每个元素包含指向前一个元素和后一个元素的两个指针。这样的结构允许高效的插入和删除操作,特别是当插入或删除操作发生在已知位置的附近时。在复杂的数据管理和操作中具有很大的灵活性和效率。下面是一个简单示例,展示了如何使用。

m0_72877724的博客 773

【C++】vector 与 string 互转——assign()

vector.assign(string.begin(), string.end()) string.assign(vector.begin(), vector.end())

weixin_44566432的博客 2189

C++ 中 std::vector 和 std::list 的区别详解

在 C++ 标准库(STL)中,std::vector 和 std::list 都是最常用的序列容器,它们都支持 push_back、insert、erase、begin()/end() 等相似接口,看起来“用法差不多”。但如果只停留在接口层面,就很容易在性能瓶颈出现时踩坑。本篇文章将一步步帮你彻底搞清楚二者的本质区别~~

m0_74824496的博客 76

Eigen::Matrix 转 std::vector 亲测ok!

【代码】Eigen::Matrix 转 std::vector 亲测ok!

4月16!的博客 1365

C++ std::tuple

std::tuple 是一个可以支持参数集的类模板 std::make_tuple 创建一个 tuple std::tie 创建一个左值引用的 tuple std::get 获取参数集合某个位置的参数 tuple_size 获取参数集数目 示例: /* static_assert(表达式, 输出的附加信息) 对表达式进行编译时的检查 is_constructible&amp;amp;lt;class T, ...

huatian5的博客 329
上一篇: C++ UML 类图介绍
下一篇: Git Merge实战手册:分支合并的智慧
Linux在秋名山
博客等级 码龄9年 225粉丝 53原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Linux在秋名山

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值