【C++ 】vector高效使用指南

1.vector 的介绍及使用

1.1 vector 的介绍

vector 的文档介绍

  1. vector 是表示可变大小数组的序列容器。

  2. 就像数组一样,vector 也采用的连续存储空间来存储元素。也就是意味着可以采用下标对 vector 的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自动处理。

  3. 本质讲,vector 使用动态分配数组来存储它的元素。当新元素插入时候,这个数组需要被重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,因为每当一个新的元素加入到容器的时候,vector 并不会每次都重新分配大小。

  4. vector 分配空间策略:vector 会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。

  5. 因此,vector 占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。

  6. 与其它动态序列容器相比(deque, list and forward_list), vector 在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。比起 list 和 forward_list统一的迭代器和引用更好。

1.2 vector 的使用

vector 学习时一定要学会查看文档:vector 在实际中非常的重要,在实际中我们熟悉常 见的接口就可以,下面列出了哪些接口是要重点掌握的

1.2.1 vector 的定义与构造函数

基本概念

vector 是 C++ 标准模板库 (STL) 中的序列容器,表示可以动态改变大小的数组,在 <vector> 头文件中定义。

构造函数详解

1. 无参构造函数 (重点)

vector();
  • 创建一个空的 vector 容器,不包含任何元素

  • 初始容量为 0,但在首次添加元素时会自动分配内存

  • 示例:

vector<int> v1; // 创建一个空的整型vector

2.数量初始化构造函数

vector(size_type n, const value_type& val = value_type());

  • 创建包含 n 个元素的 vector,每个元素初始化为 val

  • 如果未提供 val,则使用值初始化(对于内置类型,如 int,初始化为 0)

  • 示例:

vector<int> v2(5, 10);    // 包含5个元素,每个都是10: [10,10,10,10,10]
vector<int> v3(3);        // 包含3个元素,每个都是0: [0,0,0]

3.拷贝构造函数 (重点)

vector(const vector& x);
  • 创建一个新 vector,其内容与参数 x 完全相同(深拷贝)

  • 时间复杂度:O(n),需要复制所有元素

  • 示例:

vector<int> original(3, 7);  // [7,7,7]
vector<int> copy(original);  // 创建副本: [7,7,7]

4.迭代器范围构造函数

template <class InputIterator>
vector(InputIterator first, InputIterator last);
  • 使用迭代器范围 [first, last) 中的元素初始化 vector

  • 可以接受任何类型的输入迭代器(数组指针、其他容器的迭代器等)

  • 示例:

int arr[] = {1, 2, 3, 4, 5};
vector<int> v4(arr, arr + 5); // 使用数组初始化: [1,2,3,4,5]

list<int> myList = {10, 20, 30};
vector<int> v5(myList.begin(), myList.end()); // 使用list迭代器: [10,20,30]

1.2.2 vector iterator 的使用

迭代器基本概念

迭代器提供了一种统一的方法来访问容器中的元素,类似于指针的行为。

常规迭代器

1.begin() 和 end()

iterator begin() noexcept;
const_iterator begin() const noexcept;
iterator end() noexcept;
const_iterator end() const noexcept;
  • begin(): 返回指向第一个元素的迭代器

  • end(): 返回指向最后一个元素之后位置的迭代器(不是最后一个元素)

  • const版本用于const对象,防止修改元素

  • 示例:

vector<int> v = {10, 20, 30, 40};

// 使用迭代器遍历
for (auto it = v.begin(); it != v.end(); ++it) {
    cout << *it << " "; // 输出: 10 20 30 40
}

// 修改元素
for (auto it = v.begin(); it != v.end(); ++it) {
    *it += 5; // 每个元素加5
}

2.cbegin() 和 cend() (C++11)

const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;
  • 返回const迭代器,即使vector本身不是const

  • 确保不会通过迭代器修改元素

  • 示例:

vector<int> v = {1, 2, 3};
auto it = v.cbegin(); // 只能读取,不能修改 *it
// *it = 10; // 错误: 不能修改

反向迭代器

1.rbegin() 和 rend()

reverse_iterator rbegin() noexcept;
const_reverse_iterator rbegin() const noexcept;
reverse_iterator rend() noexcept;
const_reverse_iterator rend() const noexcept;
  • rbegin(): 返回指向最后一个元素的反向迭代器

  • rend(): 返回指向第一个元素之前位置的反向迭代器

  • 反向迭代器递增操作会向容器开头移动

  • 示例:

vector<int> v = {10, 20, 30, 40};

// 反向遍历
for (auto rit = v.rbegin(); rit != v.rend(); ++rit) {
    cout << *rit << " "; // 输出: 40 30 20 10
}

2.crbegin() 和 crend() (C++11)

const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;
  • 返回const反向迭代器,确保不会通过迭代器修改元素

迭代器类型总结

迭代器类型函数描述
正向迭代器begin(), end()从首元素向末尾遍历
常量正向迭代器cbegin(), cend()只读正向遍历
反向迭代器rbegin(), rend()从末元素向开头遍历
常量反向迭代器crbegin(), crend()只读反向遍历

注意事项

  1. 迭代器失效:当vector进行插入或删除操作时,可能会导致迭代器失效,需要重新获取

  2. 容量与大小:size()返回元素数量,capacity()返回已分配内存可容纳的元素数量

  3. 性能特征:

    1. 随机访问:O(1)

    2. 末尾插入/删除:平均O(1)

    3. 中间插入/删除:O(n)

关键点总结

  1. 迭代器类型:

    1. 普通迭代器:可读写

    2. 常量迭代器:只读

    3. 反向迭代器:反向遍历,可读写

    4. 常量反向迭代器:反向遍历,只读

  2. 迭代器操作:

    1. *iter:解引用,访问元素

    2. ++iter/--iter:移动到下一个/上一个位置

    3. iter + n/iter - n:随机访问(仅适用于随机访问迭代器)

  3. 注意事项:

    1. 修改容器大小(插入/删除)可能导致迭代器失效

    2. 使用常量迭代器可以防止意外修改

    3. C++11 后推荐使用 auto 关键字简化迭代器声明

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值