【c++容器】vector动态数组容器

目录

1. 基本概念

2. 常用的构造函数

3. 常用的成员函数

4. 迭代器

5. 内存管理

6.更多成员函数汇总

7.vector函数使用实例代码



如需咨询请添加个人微信:a15135158368

欢迎叨扰,多多交流


`std::vector` 是 C++ 标准模板库 (STL) 中的一个动态数组容器(可变长数组),它能够存储类型相同的对象,并且在大小变化时自动管理内存(随时添加和删除元素)。

1. 基本概念

  • 动态数组

    std::vector 类似于普通的数组,但它的大小是动态的,可以根据需要自动调整。

    与普通数组不同的是,std::vector 的大小可以在运行时增加或减少。

  • 自动内存管理

    std::vector 在内部自动管理内存分配和释放,避免了手动管理内存的复杂性。

2. 常用的构造函数

  • 默认构造函数

    创建一个空的 std::vector

    std::vector<int> vec;
  • 指定大小的构造函数

    创建一个包含 5 个元素的 std::vector

    每个元素使用类型的默认构造函数初始化。

    std::vector<int> vec(5);
  • 指定大小和初始值的构造函数

    创建一个包含 5 个元素的 std::vector,每个元素都初始化为 10。

    std::vector<int> vec(5, 10);
  • 初始化中有多个元素

    vector<int> a{1, 2, 3, 4, 5};//数组a中有五个元素,数组长度就为5
  • 复制构造函数

    使用另一个 std::vector 初始化一个新的 std::vector

    std::vector<int> vec2(vec1); //类型必须相同
    std::vector<int> vec2 = vec1;
  • 迭代器范围的构造函数

    使用其他容器或数组的迭代器范围初始化 std::vector

    std::vector<int> vec(vec1.begin(), vec1.end());
  • 二维容器初始化

    #include <iostream>
    #include <vector>
    ​
    using namespace std;
    ​
    int main() {
        // 初始化一个 3x4 的二维 vector,所有元素初始化为 0
        vector<vector<int>> vec(3, vector<int>(4, 0));
    ​
        // 输出二维 vector 的内容
        for (const auto& row : vec) {
            for (const auto& elem : row) {
                cout << elem << " ";
            }
            cout << endl;
        }
    ​
        return 0;
    }

3. 常用的成员函数

  • push_back()

    std::vector 的末尾添加元素。

    vec.push_back(20);
  • pop_back()

    移除 std::vector 末尾的元素。

    vec.pop_back();
  • size()

    返回当前存储的元素数量。

    std::cout << vec.size() << std::endl;
  • capacity()

    返回当前分配的存储空间的容量(即在不重新分配内存的情况下,std::vector 可以存储的元素个数)。

    std::cout << vec.capacity() << std::endl;
  • empty()

    判断 std::vector 是否为空。

    if (vec.empty()) {
        std::cout << "Vector is empty." << std::endl;
    }
  • clear()

    清除所有元素,使 std::vector 为空。

    vec.clear();
  • at()

    返回指定位置的元素,带边界检查。

    int val = vec.at(2);
  • operator[]

    返回指定位置的元素,不带边界检查。

    int val = vec[2];
  • insert()

    在指定位置插入元素或多个元素。

    vec.insert(vec.begin() + 1, 15);  // 在第二个位置插入15
  • erase()

    删除指定位置的元素或范围内的元素。

    vec.erase(vec.begin() + 1);  // 删除第二个元素
  • resize()

    调整 std::vector 的大小,并可指定值。

    vec.resize(10);  // 调整大小为10
    vec.reszie(n, v);       //将n个空间数值赋值为v, 如果没有默认赋值为0 
    //注意:如果之前指定过该空间的值,再次赋值时并不会覆盖。
    //以下这个例子会证明
    ​
    #include<bits/stdc++.h>
    ​
    using namespace std;
    ​
    void out(vector<int> &a) 
    { 
        for (auto &x: a) 
            cout << x << " "; cout << "\n";
    }
    ​
    int main() {
        vector<int> a(5, 1);
        out(a); // 1 1 1 1 1
        
        a.resize(10, 2);
        out(a); // 1 1 1 1 1 2 2 2 2 2
        
        a.resize(3, 3);
        out(a); // 1 1 1
        
        return 0;
    }
  • reserve()

    预先分配内存,以避免在增加元素时多次重新分配内存。

    vec.reserve(100);

4. 迭代器

类似指针,迭代器就是充当指针的作用。vi[i] 等价于 *(vi.begin() + i)

  • begin()end()

    返回 std::vector 的起始和结束迭代器。

    • end()返回的是最后一个元素的后一位置的地址

    //auto关键字:自动推导变量类型(注意:变量必须在定义时初始化;可能忽略const和引用&,如需使用需明确声明)
    for (auto it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;
  • rbegin()rend()

    返回 std::vector 的逆向迭代器。

    for (auto it = vec.rbegin(); it != vec.rend(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

5. 内存管理

  • shrink_to_fit()

    std::vector 的容量减少到与当前大小匹配,释放未使用的内存。

    vec.shrink_to_fit();
  • allocator_type

    可以自定义 std::vector 的内存分配器。

6.更多成员函数汇总

代码算法复杂度返回值类型含义
c.front()O(1)O(1)引用返回容器中的第一个数据
c.back()O(1)O(1)引用返回容器中的最后一个数据
c.at(idx)引用返回 c[idx] ,会进行边界检查,如果越界会报错,比直接使用 [] 更好一些,常在项目中使用
c.size()O(1)O(1)返回实际数据个数(unsigned类型)
c.begin()O(1)O(1)迭代器返回首元素的迭代器(通俗来说就是地址)
c.end()O(1)O(1)迭代器返回最后一个元素后一个位置的迭代器(地址)
c.empty()O(1)O(1)bool判断是否为空,为空返回真,反之返回假
c.reserve(sz)为数组提前分配sz的内存大小,即改变了 capacity 的大小,主要是为了防止在 push_back 过程中多次的内存拷贝
c.assign(beg, end)将另外一个容器[x.begin(), x.end()) 里的内容拷贝到c
c.assign(n, val)nval值拷贝到c数组中,这会清除掉容器中以前的内容,c数组的size将变为ncapacity 不会改变
c.pop_back()O(1)O(1)删除最后一个数据
c.push_back(element)O(1)O(1)在尾部加一个数据
c.emplace_back(ele)O(1)O(1)在数组中加入一个数据,和 push_back 功能基本一样,在某些情况下比它效率更高,支持传入多个构造参数
c.clear()O(N)O(N)清除容器中的所有元素
c.resize(n, v)改变数组大小为n,n个空间数值赋为v,如果没有默认赋值为0
c.insert(pos, x)O(N)O(N)向任意迭代器pos插入一个元素x
例:c.insert(c.begin() + 2, -1)-1插入c[2]的位置
c.erase(first, last)O(N)O(N)删除[first, last)的所有元素

礼貌转载,感谢!

来源: 行码棋 作者: 行码棋 链接: C++ STL总结 | 行码棋

7.vector函数使用实例代码

/**
  ******************************************************************************
  * @file           : vector_study.cpp
  * @author         : niuniu
  * @brief          : 一个 `std::vector` 容器的实例
  * @attention      : None
  * @date           : 2024/8/28
  ******************************************************************************
  */
#include <iostream>
#include <vector>
​
int main() {
    // 创建一个存储 int 类型的 vector 容器
    std::vector<int> vec;
​
    // 使用 push_back() 在 vector 的末尾添加元素
    vec.push_back(10);
    vec.push_back(20);
    vec.push_back(30);
​
    std::cout << "使用`push_back`将元素压入后的结果为 : ";
    for (int val : vec) {
        std::cout << val << " "; // 输出: 10 20 30
    }
    std::cout << std::endl;
​
    // 使用 pop_back() 移除末尾的元素
    vec.pop_back();
    std::cout << "使用`pop_back`移除末尾元素后的结果为 : ";
    for (int val : vec) {
        std::cout << val << " "; // 输出: 10 20
    }
    std::cout << std::endl;
​
    // 使用 size() 获取当前元素数量
    std::cout << "当前容器的元素数量为(size) : " << vec.size() << std::endl; // 输出: 2
​
    // 使用 capacity() 获取当前分配的容量
    std::cout << "当前分配的容量为(capacity) : " << vec.capacity() << std::endl; // 输出: 4
​
    // 使用 empty() 判断 vector 是否为空
    if (!vec.empty()) {
        std::cout << "容器不为空" << std::endl;
    }
​
    // 使用at()访问元素
    try         //异常处理机制,如果在try语句中发生异常,会跳到catch语句
    {
        std::cout << "索引1处的元素为 (at) : " << vec.at(1) << std::endl;
    }
    catch (const std::out_of_range& e)      //根据异常的类型,决定是否处理该异常,参数指定可以处理异常的类型
    {
        //what()是异常对象的一个成员函数,返回值会描述错误的消息
        std::cout << "错误:超出范围 (what) : " << e.what() << std::endl;
    }
​
    // 使用 operator[] 访问指定位置的元素(不带边界检查)
    std::cout << "索引0处的元素为 (重载索引[]) : " << vec[0] << std::endl; // 输出: 10
​
    // 使用 insert() 在指定位置插入元素
    vec.insert(vec.begin() + 1, 15);
    std::cout << "在索引1处插入后 (insert) : ";
    for (int val : vec) {
        std::cout << val << " "; // 输出: 10 15 20
    }
    std::cout << std::endl;
​
    // 使用 erase() 删除指定位置的元素
    vec.erase(vec.begin());
    std::cout << "删除第一个元素后 (erase) : ";
    for (int val : vec) {
        std::cout << val << " "; // 输出: 15 20
    }
    std::cout << std::endl;
​
    // 使用 resize() 调整 vector 的大小
    vec.resize(4, 100);  // 如果增加大小,使用 100 进行填充
    std::cout << "调整为4个元素后 (resize) : ";
    for (int val : vec) {
        std::cout << val << " "; // 输出: 15 20 100 100
    }
    std::cout << std::endl;
​
    // 使用 reserve() 预先分配内存
    vec.reserve(10);
    std::cout << "储备后容量(10) (reserve) : " << vec.capacity() << std::endl; // 输出: 10
​
    // 使用 clear() 清空所有元素
    vec.clear();
    std::cout << "清除后的尺寸 (clear) : " << vec.size() << std::endl; // 输出: 0
    std::cout << "清除后的容量 (clear) : " << vec.capacity() << std::endl; // 输出: 10
​
    // 使用 begin() 和 end() 获取起始和结束迭代器
    vec.push_back(50);
    vec.push_back(60);
    std::cout << "使用begin()和end() 遍历: ";
    for (auto it = vec.begin(); it != vec.end(); ++it) {
        std::cout << *it << " "; // 输出: 50 60
    }
    std::cout << std::endl;
​
    // 使用 rbegin() 和 rend() 获取逆向迭代器
    std::cout << "使用rbegin()和rend(): ";
    for (auto rit = vec.rbegin(); rit != vec.rend(); ++rit) {
        std::cout << *rit << " "; // 输出: 60 50
    }
    std::cout << std::endl;
​
    // 使用 shrink_to_fit() 释放未使用的内存
    vec.shrink_to_fit();
    std::cout << "收缩后的容量 : " << vec.capacity() << std::endl; // 输出: 2
​
    // 使用 allocator_type 自定义内存分配器(高级用法,不常见)
    std::vector<int, std::allocator<int>> customAllocatorVec;
    customAllocatorVec.push_back(70);
    std::cout << "使用自定义分配器 (allocator_type): " << customAllocatorVec[0] << std::endl; // 输出: 70
​
    return 0;
}

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值