仓库链接
本仓库提供STL相关每一篇文章的完整可运行示例代码。

git clone https://github.com/MaikieMaiky/cpp_STL.git

vector基本概念

  • vector数据结构和数组非常相似,也成为单端数组(只在尾端可以进行push/pop)

vector与普通数组的区别:

  • 普通数组是静态数组,大小固定不可变
  • vector是动态数组,大小可以动态扩展

动态扩展

  • 扩展时寻找一块更大的内存空间,拷贝原数据到新空间,释放原空间
        front()                  back()
       ----------------------------------
       |                      ----->         push_back()
       | 1    2    _    3    4    5  
^      | ^          ^             ^      ^   pop_back()
|      --|----------|-------------|------|---
v.rend() v.begin()  insert()  v.rbegin()  v.end()
  • 常用iterator为v.begin()和v.end
  • vector 的 iterator 支持随机访问

vector构造函数

原型:

  • vector(); // 无参构造函数

  • vector(int n, const T& value); // 拷贝n个value到vector中

  • vector(const vector& v); // 拷贝构造函数

  • vector(InputIterator first, InputIterator last); // 复制[first,last)范围的元素到vector中,一般写作 vector(v.begin(), v.end())

  • 示例

    // vector的构造函数
    /**
     * vector();                                        // 无参构造函数
     * vector(int n, const T& value);                   // 拷贝n个value到vector中
     * vector(const vector& v);                         // 拷贝构造函数
     * vector(InputIterator first, InputIterator last); // 复制[first,
     * last)范围的元素到vector中,一般写作vector(v.begin(), v.end())
     */
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    void print_vector(vector<int> v)
    {
        for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    
    void test0() 
    {
        // 1. 无参构造
        vector<int> v1;
        for (int i = 0; i < 10; i++)
        {
            v1.push_back(i);
        }
        print_vector(v1);
    
        // 2. 拷贝n个value到vector中
        vector<int> v2(10, 1);
        print_vector(v2);
    
        // 3. 拷贝构造函数
        vector<int> v3(v1);
        print_vector(v3);
        
        // 4. 复制[first, last)范围的元素到vector中
        vector<int> v4(v1.begin(), v1.end());
        print_vector(v4);
    }
    
    int main()
    {
        test0();
        return 0;
    }
    

vector赋值操作

原型:

  • vector& operator=(const vector& v); // 重载=操作符

  • assign(int n, const T& value); // 复制n个value到vector中

  • assign(InputIterator first, InputIterator last); // 复制[first, last)范围的元素到vector中,一般写作 assign(v.begin(), v.end())

  • 示例

    // vector的赋值操作
    /**
     * vector& operator=(const vector& v);              // 重载=操作符
     * assign(int n, const T& value);                   // 复制n个value到vector中
     * assign(InputIterator first, InputIterator last); // 复制[first, last)范围的元素到vector中,一般写作assign(v.begin(), v.end())
     */
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    void print_vector(vector<int> v)
    {
        for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    
    void test0()
    {
        // 无参构造
        vector<int> v1;
        for (int i = 0; i < 10; i++)
        {
            v1.push_back(i);
        }
        print_vector(v1);
    
        // 重载=操作符
        vector<int> v2;
        v2 = v1;
        print_vector(v2);
        
        // 复制n个value到vector中
        vector<int> v3;
        v3.assign(10, 100);
        print_vector(v3);
    
        // 复制[first, last)范围的元素到vector中
        vector<int> v4;
        v4.assign(v1.begin(), v1.end());
        print_vector(v4);
    }
    
    int main()
    {
        test0();
        return 0;
    }
    

vector容量和大小

原型:

  • empty(); // 判断vector是否为空

  • capacity(); // 返回vector的容量

  • size(); // 返回vector中元素的个数

  • resize(int size); // 重新指定vector的容量,若容器变长,则以默认值填充新位置。
    // 若容器变短,则超出容器长度的元素被删除。

  • resize(int size, const T& value); // 重新指定vector的容量,若容器变长,则以value填充新位置。
    // 若容器变短,则超出容器长度的元素被删除。

  • 示例

    // vector的容量与大小
    /**
     * empty();                             // 判断vector是否为空
     * capacity();                          // 返回vector的容量
     * size();                              // 返回vector中元素的个数
     * resize(int size);                    // 重新指定vector的容量,若容器变长,则以默认值填充新位置。
     *                                      // 若容器变短,则超出容器长度的元素被删除。
     * resize(int size, const T& value);    // 重新指定vector的容量,若容器变长,则以value填充新位置。
     *                                      // 若容器变短,则超出容器长度的元素被删除。
     */
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    void print_vector(vector<int> v)
    {
        for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    
    void test0()
    {
        vector<int> v1;
        // 1. 判断是否为空
        if (v1.empty())
        {
            cout << "v1 is empty" << endl;
        }
        else
        {
            cout << "v1 is not empty" << endl;
        }
    
        // 2. 添加元素
        for (int i = 0; i < 5; i++)
        {
            v1.push_back(i);
        }
    
        // 3. 查看容量和大小
        cout << "v1 capacity: " << v1.capacity() << endl;
        cout << "v1 size: " << v1.size() << endl;
        print_vector(v1);
    
        // 4. 重新指定大小, 以默认值填充新位置
        v1.resize(15);
        print_vector(v1);
    
        // 5. 重新指定大小, 以value填充新位置
        v1.resize(20, 100);
        print_vector(v1);
    
        // 6. 重新指定大小,超出容器长度的元素被删除
        v1.resize(3);
        print_vector(v1);
    }
    
    int main()
    {
        test0();
        return 0;
    }
    

vector插入和删除

原型:

  • push_back(const T& value); // 在末尾添加元素

  • pop_back(); // 删除末尾的元素

  • insert(iterator pos, const T& value); // 在pos位置插入value

  • insert(iterator pos, int n, const T& value); // 在pos位置插入n个value

  • erase(iterator pos); // 删除pos位置的元素

  • erase(iterator first, iterator last); // 删除[first, last)范围的元素

  • clear(); // 清空vector

  • 示例

    // vector的插入和删除
    /**
     * push_back(const T& value);                       // 在末尾添加元素
     * pop_back();                                      // 删除末尾的元素
     * insert(iterator pos, const T& value);            // 在pos位置插入value
     * insert(iterator pos, int n, const T& value);     // 在pos位置插入n个value
     * erase(iterator pos);                             // 删除pos位置的元素
     * erase(iterator first, iterator last);            // 删除[first, last)范围的元素
     * clear();                                         // 清空vector
     */
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    void print_vector(vector<int> v)
    {
        for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    
    void test0()
    {
        vector<int> v;
        for (int i = 0; i < 10; i++)
        {
            v.push_back(i);
        }
        print_vector(v);
    
        // 1. 在末尾添加元素
        v.push_back(100);
        print_vector(v);
        
        // 2. 删除末尾的元素
        for (int i = 0; i < 5; i++)
        {
            v.pop_back();
        }
        print_vector(v);
    
        // 3. 在pos位置插入value
        v.insert(v.begin(), 100);
        print_vector(v);
        
        // 4. 在pos位置插入n个value
        v.insert(v.begin(), 2, 88);
        print_vector(v);
    
        // 5. 删除pos位置的元素
        v.erase(v.begin() + 2);
        print_vector(v);
    
        // 6. 删除[first, last)范围的元素
        v.erase(v.begin() + 1, v.begin() + 3);
        print_vector(v);
    
        // 7. 清空vector
        v.clear();
        print_vector(v);
    
    }
    
    int main()
    {
        test0();
        return 0;
    }
    

注意:insert和erase要传入迭代器,入门时我们可以直接把迭代器当作指针来使用,比如可以直接通过*iterator来取出容器中的元素


vector数据存取

原型:

  • at(int idx); // 通过at方法访问元素

  • operator[]; // 通过[ ]访问元素,类似C风格数组访问方式

  • front(); // 访问第一个元素

  • back(); // 访问最后一个元素

  • 示例

    // vector的数据存取
    /**
     * at(int idx);          // 通过索引访问元素
     * operator[];           // 通过索引访问元素
     * front();              // 访问第一个元素
     * back();               // 访问最后一个元素
     */
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    void test0()
    {
        vector<int> v;
        for (int i = 0; i < 10; i++)
        {
            v.push_back(i);
        }
    
        // 1. 通过索引访问元素
        cout << "v[0] = " << v[0] << endl;
        cout << "v.at(2) = " << v.at(2) << endl;
        
        // 2. 访问第一个元素
        cout << "the first element is " << v.front() << endl;
    
        // 3. 访问最后一个元素
        cout << "the last element is " << v.back() << endl;
    }
    
    int main()
    {
        test0();
        return 0;
    }
    

除了使用迭代器获取元素,还可以使用at, [ ]来获取


vector容器互换

原型:

  • swap(vector& vec); // 将vec与当前vector进行交换

  • 实际用法 - 内存收缩vector<int>(vec).swap(vec)
    创建了一个vector → 使用后vector的capacity较大,而size很小 → 通过创建一个匿名对象(临时对象)通过拷贝构造复制当前的size,并设置当前size为capacity → 使用swap交换 → 原vec指向匿名对象的内容 → 匿名对象负责原vec内容的析构

  • 示例

    // vector容器互换
    /**
     * swap(vector& vec); // 将vec与当前vector进行交换
     */
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    void print_vector(vector<int> v)
    {
        for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
        {
            cout << *it << " ";
        }
        cout << endl;
    }
    
    void test0()
    {
        vector<int> v1;
        for (int i = 0; i < 10; i++)
        {
            v1.push_back(i);
        }
        cout << "v1 = ";
        print_vector(v1);
    
        vector<int> v2;
        for (int i = 10; i > 0; i--)
        {
            v2.push_back(i);
        }
        cout << "v2 = ";
        print_vector(v2);
    
        // 互换
        v1.swap(v2);
        cout << "v1 = ";
        print_vector(v1);
        cout << "v2 = ";
        print_vector(v2);
    }
    
    // 实际应用 
    void test1()
    {
        vector<int> v;
        for (int i = 0; i < 100000; i++)
        {
            v.push_back(i);
        }
        cout << "v capacity: " << v.capacity() << endl;
        cout << "v size: " << v.size() << endl;
    
        // size缩小为3 capacity不变
        v.resize(3);
        cout << "after resize" << endl;
        cout << "v capacity: " << v.capacity() << endl;
        cout << "v size: " << v.size() << endl;
    
        // 内存收缩 vector<int>(不写名字)(v) 匿名对象 拷贝构造函数复制原对象的size 并以此为capacity 然后与原对象交换指向 匿名函数负责释放原对象内存
        vector<int>(v).swap(v);
        cout << "after swap" << endl;
        cout << "v capacity: " << v.capacity() << endl;
        cout << "v size: " << v.size() << endl;
    }
    
    int main()
    {
        // test0();
        test1();
        return 0;
    }
    

vector预留空间

提前一次分配大块内存给capacity,减少vector动态扩容的次数,提高效率

特点

  • 预留位置不初始化
  • 预留位置的元素不可访问

原型

  • reserve(int len); // 预留len个元素的容量

  • 示例

    // vector预留空间
    /**
     * reserve(int len); // 预留len个元素的容量
     */
    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    // 通过提前预留大块空间 减少vector扩容次数 提高效率
    void test0()
    {
        vector<int> v;
        
        // 开关注释 对比是否预留空间对扩容次数的影响
        // v.reserve(100000);
    
        // 记录每次扩容的地址 如果地址发生变化 则说明发生了扩容
        int* p = NULL;
        int count = 0;
        for (int i = 0; i < 100000; i++)
        {
            v.push_back(i);
            if (p != &v[0])
            {
                p = &v[0];
                count++;
            }
        }
        cout << "the number of times of expansion: " << count << endl;
    }
    
    int main()
    {
        test0();
        return 0;
    }
    

更多推荐