C++ 学习杂记04:std::vector 类

概述

std::vector是 C++ 标准模板库(STL)中提供的动态数组容器。它能够在运行时动态调整大小,提供随机访问迭代器,是 C++ 中最常用的容器之一。

头文件

复制代码
#include <vector>

类模板声明

复制代码
template<
    class T,
    class Allocator = std::allocator<T>
> class vector;

构造函数

1. 默认构造函数

复制代码
std::vector<T> vec;  // 创建空vector

2. 指定大小构造函数

复制代码
std::vector<T> vec(10);           // 10个默认初始化的元素
std::vector<T> vec(10, value);    // 10个值为value的元素

3. 范围构造函数

复制代码
std::vector<T> vec(other.begin(), other.end());  // 从迭代器范围构造

4. 拷贝构造函数

复制代码
std::vector<T> vec(other);  // 深拷贝

5. 初始化列表构造函数

复制代码
std::vector<T> vec = {1, 2, 3, 4, 5};

常用成员函数

元素访问

复制代码
// 返回指定位置的引用,不进行边界检查
T& operator[](size_type pos);
const T& operator[](size_type pos) const;

// 返回指定位置的引用,进行边界检查(可能抛出std::out_of_range)
T& at(size_type pos);
const T& at(size_type pos) const;

// 返回第一个元素的引用
T& front();
const T& front() const;

// 返回最后一个元素的引用
T& back();
const T& back() const;

// 返回底层数组的指针
T* data() noexcept;
const T* data() const noexcept;

容量相关

复制代码
// 检查是否为空
bool empty() const noexcept;

// 返回元素数量
size_type size() const noexcept;

// 返回最大可能元素数量
size_type max_size() const noexcept;

// 预留容量,减少重新分配次数
void reserve(size_type new_cap);

// 返回当前分配的存储容量
size_type capacity() const noexcept;

// 请求移除未使用的容量
void shrink_to_fit();

修改操作

复制代码
// 清空所有元素
void clear() noexcept;

// 在末尾插入元素
void push_back(const T& value);
void push_back(T&& value);

// 移除末尾元素
void pop_back();

// 在指定位置插入元素
iterator insert(const_iterator pos, const T& value);
iterator insert(const_iterator pos, T&& value);
iterator insert(const_iterator pos, size_type count, const T& value);

// 擦除指定位置的元素
iterator erase(const_iterator pos);
iterator erase(const_iterator first, const_iterator last);

// 调整容器大小
void resize(size_type count);
void resize(size_type count, const T& value);

// 交换两个vector的内容
void swap(vector& other) noexcept;

示例代码

基本使用

复制代码
#include <iostream>
#include <vector>

int main() {
    // 创建vector
    std::vector<int> numbers = {1, 2, 3, 4, 5};
    
    // 添加元素
    numbers.push_back(6);
    
    // 访问元素
    std::cout << "第一个元素: " << numbers.front() << std::endl;
    std::cout << "最后一个元素: " << numbers.back() << std::endl;
    std::cout << "第三个元素: " << numbers[2] << std::endl;
    
    // 遍历vector
    std::cout << "所有元素: ";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
    
    // 使用迭代器
    std::cout << "使用迭代器: ";
    for (auto it = numbers.begin(); it != numbers.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
    
    return 0;
}

容量管理示例

复制代码
#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec;
    
    std::cout << "初始容量: " << vec.capacity() << std::endl;
    
    // 预留空间以提高性能
    vec.reserve(100);
    std::cout << "预留100个元素后的容量: " << vec.capacity() << std::endl;
    
    // 添加元素
    for (int i = 0; i < 50; ++i) {
        vec.push_back(i);
    }
    
    std::cout << "添加50个元素后的大小: " << vec.size() << std::endl;
    std::cout << "添加50个元素后的容量: " << vec.capacity() << std::endl;
    
    return 0;
}

插入和删除示例

复制代码
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec = {1, 2, 3, 5, 6};
    
    // 在位置3插入元素4
    auto it = vec.begin() + 3;
    vec.insert(it, 4);
    
    // 删除元素2
    vec.erase(std::remove(vec.begin(), vec.end(), 2), vec.end());
    
    // 输出结果
    for (int num : vec) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
    
    return 0;
}

性能特征

时间复杂度

  • 随机访问:O(1)

  • 在末尾插入/删除:O(1)(平均情况,不考虑重新分配)

  • 在开头或中间插入/删除:O(n)

  • 查找:O(n)(无序情况下)

空间复杂度

  • 连续内存存储

  • 可能需要额外的内存用于管理

使用建议

优点

  1. 随机访问:支持常数时间复杂度的随机访问

  2. 缓存友好:数据连续存储,缓存局部性好

  3. 动态扩容:自动管理内存,无需手动分配

  4. 丰富接口:提供丰富的成员函数和算法支持

注意事项

  1. 中间插入/删除:在vector中间插入或删除元素效率较低

  2. 内存重新分配:扩容时可能导致迭代器失效

  3. 预留空间 :如果知道大致元素数量,使用reserve()提高性能

  4. 大对象:存储大对象时,考虑使用指针或智能指针

迭代器失效规则

  • 插入元素时:如果导致重新分配,所有迭代器、指针、引用失效

  • 插入元素时:如果未重新分配,插入点后的迭代器失效

  • 删除元素时:被删除元素后的迭代器失效

  • reserve():如果增加容量,所有迭代器、指针、引用可能失效

相关算法

复制代码
#include <algorithm>

// 排序
std::sort(vec.begin(), vec.end());

// 查找
auto it = std::find(vec.begin(), vec.end(), value);

// 反转
std::reverse(vec.begin(), vec.end());

// 删除特定元素
vec.erase(std::remove(vec.begin(), vec.end(), value), vec.end());

总结

std::vector是 C++ 中最常用、最通用的容器之一。它结合了数组的随机访问效率和动态数组的灵活性,适用于大多数需要顺序存储数据的场景。正确使用 vector可以提高代码的性能和可维护性。

相关推荐
代钦塔拉1 小时前
Qt调试技巧:解决DLL输入点错误指南
c++·qt
熬夜敲代码的猫1 小时前
C++:模板精讲
c++·算法·模板
兩尛1 小时前
C++面向对象和类相关
java·c++·面试
凯瑟琳.奥古斯特2 小时前
C++变量命名进阶技巧
开发语言·c++
ximu_polaris3 小时前
设计模式(C++)-行为型模式-观察者模式
c++·观察者模式·设计模式
故事和你914 小时前
洛谷-算法2-1-前缀和、差分与离散化1
开发语言·数据结构·c++·算法·深度优先·动态规划·图论
handler0112 小时前
从零实现自动化构建:Linux Makefile 完全指南
linux·c++·笔记·学习·自动化
我头发多我先学14 小时前
C++ 模板全解:从泛型编程初阶到特化、分离编译进阶
java·开发语言·c++
星星码️14 小时前
C++选择题练习(一)
开发语言·c++