最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++?vector容器底層深度剖析與模擬實(shí)現(xiàn)代碼示例

 更新時間:2026年01月05日 09:44:23   作者:近津薪荼  
vector容器是STL中最常用的容器之一,它和array容器非常類似,都可以看做是對C++普通數(shù)組的升級版,這篇文章主要介紹了C++?vector容器底層深度剖析與模擬實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下

1 模板的使用說明

在C++中,模板是實(shí)現(xiàn)泛型編程的重要工具,它允許我們編寫與數(shù)據(jù)類型無關(guān)的代碼。vector容器正是通過模板技術(shù)實(shí)現(xiàn)的,可以存儲任意類型的數(shù)據(jù):

template<class T>
class vector
{
    // ... 實(shí)現(xiàn)細(xì)節(jié)
};

這里的T是類型參數(shù),當(dāng)我們創(chuàng)建vector對象時,需要指定具體的類型

vector<int> intVector;      // 存儲int類型的vector
vector<string> strVector;   // 存儲string類型的vector
vector<double> dblVector;   // 存儲double類型的vector

模板的使用讓vector具有了極強(qiáng)的通用性,可以容納各種數(shù)據(jù)類型,從基本類型到自定義類類型。

2 vector深度剖析及模擬實(shí)現(xiàn)

2.1 vector的成員變量

vector底層使用動態(tài)數(shù)組實(shí)現(xiàn),通過三個指針來管理內(nèi)存:

private:
    iterator _start = nullptr;          // 指向數(shù)組的開始位置
    iterator _finish = nullptr;         // 指向最后一個元素的下一個位置
    iterator _end_of_storage = nullptr; // 指向分配內(nèi)存的末尾

在這里,給了三個指針缺省值nullptr初始化。

2.2 構(gòu)造函數(shù)

vector提供了多種構(gòu)造函數(shù)來滿足不同的初始化需求:、

2.2.1 指定大小和初始值的構(gòu)造函數(shù)

vector(size_t n, const T& val = T())
{
    reserve(n);
    for (size_t i = 0; i < n; i++)
    {
        push_back(val);
    }
}

使用示例:

vector<int> v1(5);        // 包含5個0的vector
vector<int> v2(3, 10);    // 包含3個10的vector
vector<string> v3(2, "hello"); // 包含2個"hello"的vector

2.2.2 迭代器范圍構(gòu)造函數(shù)

template <class InputIterator>
vector(InputIterator first, InputIterator last)
{
    while (first != last)
    {
        push_back(*first);
        ++first;
    }
}

這個構(gòu)造函數(shù)是函數(shù)模板,可以接受任意類型的迭代器:

int arr[] = {1, 2, 3, 4, 5};
vector<int> v1(arr, arr + 5);           // 從數(shù)組構(gòu)造
vector<int> v2(v1.begin(), v1.end());   // 從另一個vector構(gòu)造

2.2.3 拷貝構(gòu)造函數(shù)(現(xiàn)代寫法)

vector(const vector<T>& v)
{
    vector<T> tmp(v.begin(), v.end());
    swap(tmp);
}

現(xiàn)代寫法通過創(chuàng)建臨時對象并交換資源,代碼簡潔且異常安全~

2.3 賦值運(yùn)算符重載

vector<T>& operator=(vector<T> tmp)
{
    swap(tmp);
    return *this;
}

2.4 容量相關(guān)操作

2.4.1 reserve 開空間

void reserve(size_t n)
{
    if (n > capacity())
    {
        size_t sz = size();
        T* tmp = new T[n];
        if (_start)
        {
            for (size_t i = 0; i < sz; i++)
            {
                std::swap(tmp[i], _start[i]);
            }
            delete[] _start;
        }
        _start = tmp;
        _finish = _start + sz;
        _end_of_storage = _start + n;
    }
}
  • 使用std::swap而不是直接賦值,這樣可以高效地交換資源()

  • 如果直接使用memcpy,對于管理資源的類(如string)會導(dǎo)致淺拷貝問題!

  • 重新計算_finish_end_of_storage指針

2.4.2 用resize 調(diào)整大小

void resize(size_t n, T val = T())
{
    if (n < size())
    {
        // 縮小size,只是移動_finish指針
        _finish = _start + n;
    }
    else
    {
        reserve(n);  // 可能需要擴(kuò)容
        while (_finish < _start + n)
        {
            *_finish = val;
            ++_finish;
        }
    }
}

這里使用匿名對象做缺省參數(shù)。

使用示例:

vector<int> v = {1, 2, 3};
v.resize(5);      // 變?yōu)?{1, 2, 3, 0, 0}
v.resize(2);      // 變?yōu)?{1, 2}

2.4.3 size和capacity

size_t capacity() const
{
    return _end_of_storage - _start;
}

size_t size() const
{
    return _finish - _start;
}

2.5 元素訪問操作

2.5.1 下標(biāo)運(yùn)算符

T& operator[](size_t i)
{
    assert(i < size());
    return _start[i];
}

const T& operator[](size_t i) const
{
    assert(i < size());
    return _start[i];
}

提供const和非const版本,支持讀寫訪問只讀訪問

2.6 修改操作

2.6.1 push_back 尾部添加元素

void push_back(const T& x)
{
    if (_finish == _end_of_storage)
    {
        reserve(capacity() == 0 ? 4 : capacity() * 2);
    }
    *_finish = x;
    ++_finish;
}

擴(kuò)容策略:初始為0時分配4個元素空間,否則每次擴(kuò)容為原來的2倍。

2.6.2 pop_back 尾部刪除元素

void pop_back()
{
    assert(!empty());
    --_finish;
}

2.6.3 insert 在指定位置插入元素

iterator insert(iterator pos, const T& x)
{
    assert(pos >= _start);
    assert(pos <= _finish);

    // 擴(kuò)容
    if (_finish == _end_of_storage)
    {
        size_t len = pos - _start;
        reserve(capacity() == 0 ? 4 : capacity() * 2);
        pos = _start + len;
    }

    // 挪動數(shù)據(jù)
    iterator end = _finish - 1;
    while (end >= pos)
    {
        *(end + 1) = *end;
        --end;
    }

    *pos = x;
    ++_finish;
    return pos;
}

擴(kuò)容后需要重新計算pos的位置,因為_start可能改變了。

2.6.4 erase 刪除指定位置元素

iterator erase(iterator pos)
{
    assert(pos >= _start);
    assert(pos < _finish);

    iterator it = pos + 1;
    while (it != _finish)
    {
        *(it - 1) = *it;
        ++it;
    }

    --_finish;
    return pos;
}

3 vector迭代器失效問題

迭代器失效是使用vector時需要特別注意的問題,不當(dāng)使用會導(dǎo)致未定義行為。

3.1 insert失效問題

當(dāng)在vector中插入元素時,如果引起擴(kuò)容,所有迭代器都會失效。

void test_vector2()
{
    bit::vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    
    auto it = v.begin() + 3;
    v.insert(v.begin(), 0);  // 可能引起擴(kuò)容
    
    // insert以后,it失效了,不能再使用
    // *it = 10;  // 錯誤!未定義行為
}

3.2 erase失效問題

erase操作會使被刪除元素及其后面所有元素的迭代器失效。

void test_vector3()
{
    bit::vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
    
    auto it = v.begin() + 2;
    v.erase(v.begin());  // 刪除第一個元素
    
    // it失效了,不能訪問,訪問結(jié)果未定義
    // cout << *it << endl;  // 錯誤!
}

3.3 刪除所有的偶數(shù)

正確使用erase刪除元素的模式:

void test_vector4()
{
    bit::vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
    v.push_back(6);
    
    // 正確做法:接收erase的返回值
    auto it = v.begin();
    while (it != v.end())
    {
        if (*it % 2 == 0)
        {
            it = v.erase(it);  // erase返回下一個有效迭代器
        }
        else
        {
            ++it;
        }
    }
    
    // 錯誤做法:直接遞增迭代器
    // auto it = v.begin();
    // while (it != v.end())
    // {
    //     if (*it % 2 == 0)
    //     {
    //         v.erase(it);  // erase后it失效
    //     }
    //     ++it;  // 錯誤:對失效迭代器遞增
    // }
}

3.4 不同編譯器對迭代器失效的檢查

不同編譯器對迭代器失效的檢查嚴(yán)格程度不同:

  • Debug模式下通常會進(jìn)行嚴(yán)格的迭代器檢查

  • Release模式下可能沒有檢查,導(dǎo)致難以發(fā)現(xiàn)的bug

  • Linux的gcc編譯器檢查就會比較寬松

3.5 擴(kuò)容之后,迭代器已經(jīng)失效了

vector<int> v = {1, 2, 3};
auto it = v.begin();
v.push_back(4);  // 可能引起擴(kuò)容
// it已經(jīng)失效,不能再使用

3.6 erase刪除的迭代器如果是最后一個元素

vector<int> v = {1, 2, 3};
auto it = v.begin() + 2;  // 指向3
it = v.erase(it);         // 刪除最后一個元素
// 此時it == v.end(),不能解引用

3.7 string的迭代器失效

與vector類似,string在插入、擴(kuò)容操作、erase之后,迭代器也會失效。

4 本文代碼完整展示

(一)vector.h

#pragma once
#include <iostream>
#include <assert.h>
using namespace std;

namespace bit
{
    template<class T>
    class vector
    {
    public:
        typedef T* iterator;
        typedef const T* const_iterator;

        iterator begin()
        {
            return _start;
        }

        iterator end()
        {
            return _finish;
        }

        const_iterator begin() const
        {
            return _start;
        }

        const_iterator end() const
        {
            return _finish;
        }

        // 構(gòu)造函數(shù) - 指定大小和初始值
        vector(size_t n, const T& val = T())
        {
            reserve(n);
            for (size_t i = 0; i < n; i++)
            {
                push_back(val);
            }
        }

        vector(int n, const T& val = T())
        {
            reserve(n);
            for (int i = 0; i < n; i++)
            {
                push_back(val);
            }
        }

        // 迭代器范圍構(gòu)造函數(shù)
        template <class InputIterator>
        vector(InputIterator first, InputIterator last)
        {
            while (first != last)
            {
                push_back(*first);
                ++first;
            }
        }

        // 默認(rèn)構(gòu)造函數(shù)
        vector() = default;

        // 拷貝構(gòu)造函數(shù)(現(xiàn)代寫法)
        vector(const vector<T>& v)
        {
            vector<T> tmp(v.begin(), v.end());
            swap(tmp);
        }

        // 賦值運(yùn)算符(現(xiàn)代寫法)
        vector<T>& operator=(vector<T> tmp)
        {
            swap(tmp);
            return *this;
        }

        // 交換兩個vector
        void swap(vector<T>& v)
        {
            std::swap(_start, v._start);
            std::swap(_finish, v._finish);
            std::swap(_end_of_storage, v._end_of_storage);
        }

        // 清空元素
        void clear()
        {
            _finish = _start;
        }

        // 判斷是否為空
        bool empty() const
        {
            return _start == _finish;
        }

        // 預(yù)留空間
        void reserve(size_t n)
        {
            if (n > capacity())
            {
                size_t sz = size();
                T* tmp = new T[n];
                if (_start)
                {
                    for (size_t i = 0; i < sz; i++)
                    {
                        std::swap(tmp[i], _start[i]);
                    }
                    delete[] _start;
                }
                _start = tmp;
                _finish = _start + sz;
                _end_of_storage = _start + n;
            }
        }

        // 調(diào)整大小
        void resize(size_t n, T val = T())
        {
            if (n < size())
            {
                _finish = _start + n;
            }
            else
            {
                reserve(n);
                while (_finish < _start + n)
                {
                    *_finish = val;
                    ++_finish;
                }
            }
        }

        // 獲取容量
        size_t capacity() const
        {
            return _end_of_storage - _start;
        }

        // 獲取元素個數(shù)
        size_t size() const
        {
            return _finish - _start;
        }

        // 下標(biāo)運(yùn)算符
        T& operator[](size_t i)
        {
            assert(i < size());
            return _start[i];
        }

        const T& operator[](size_t i) const
        {
            assert(i < size());
            return _start[i];
        }

        // 尾部添加元素
        void push_back(const T& x)
        {
            if (_finish == _end_of_storage)
            {
                reserve(capacity() == 0 ? 4 : capacity() * 2);
            }
            *_finish = x;
            ++_finish;
        }

        // 尾部刪除元素
        void pop_back()
        {
            assert(!empty());
            --_finish;
        }

        // 在指定位置插入元素
        iterator insert(iterator pos, const T& x)
        {
            assert(pos >= _start);
            assert(pos <= _finish);

            if (_finish == _end_of_storage)
            {
                size_t len = pos - _start;
                reserve(capacity() == 0 ? 4 : capacity() * 2);
                pos = _start + len;
            }

            iterator end = _finish - 1;
            while (end >= pos)
            {
                *(end + 1) = *end;
                --end;
            }

            *pos = x;
            ++_finish;
            return pos;
        }

        // 刪除指定位置元素
        iterator erase(iterator pos)
        {
            assert(pos >= _start);
            assert(pos < _finish);

            iterator it = pos + 1;
            while (it != _finish)
            {
                *(it - 1) = *it;
                ++it;
            }

            --_finish;
            return pos;
        }

        // 析構(gòu)函數(shù)
        ~vector()
        {
            if (_start)
            {
                delete[] _start;
                _start = _finish = _end_of_storage = nullptr;
            }
        }

    private:
        iterator _start = nullptr;
        iterator _finish = nullptr;
        iterator _end_of_storage = nullptr;
    };
}

(二)Test.c

#include "vector.h"
#include <iostream>
using namespace std;

namespace bit
{
    // 打印vector內(nèi)容
    void Print(const vector<int>& v)
    {
        for (auto e : v)
        {
            cout << e << " ";
        }
        cout << endl;
    }

    // 測試基本操作
    void test_vector1()
    {
        cout << "測試基本操作:" << endl;
        bit::vector<int> v;
        v.push_back(1);
        v.push_back(2);
        v.push_back(3);
        v.push_back(4);
        v.push_back(5);
        
        v[0]++;  // 修改第一個元素
        
        Print(v);
        
        // 范圍for遍歷
        for (auto e : v)
        {
            cout << e << " ";
        }
        cout << endl;
    }

    // 測試insert操作
    void test_vector2()
    {
        cout << "\n測試insert操作:" << endl;
        bit::vector<int> v;
        v.push_back(1);
        v.push_back(2);
        v.push_back(3);
        v.push_back(4);
        Print(v);

        v.insert(v.begin(), 0);  // 頭部插入
        Print(v);

        // 注意:insert后迭代器可能失效
        auto it = v.begin() + 3;
        v.insert(it, 30);  // 指定位置插入
        Print(v);
    }

    // 測試erase操作
    void test_vector3()
    {
        cout << "\n測試erase操作:" << endl;
        bit::vector<int> v;
        v.push_back(1);
        v.push_back(2);
        v.push_back(3);
        v.push_back(4);
        v.push_back(5);
        Print(v);

        v.erase(v.begin());  // 刪除第一個元素
        Print(v);

        auto it = v.begin() + 2;
        v.erase(it);  // 刪除指定位置元素
        Print(v);
    }

    // 測試刪除特定元素(刪除所有偶數(shù))
    void test_vector4()
    {
        cout << "\n測試刪除所有偶數(shù):" << endl;
        bit::vector<int> v;
        v.push_back(1);
        v.push_back(2);
        v.push_back(2);
        v.push_back(3);
        v.push_back(4);
        v.push_back(5);
        v.push_back(6);
        
        cout << "刪除前: ";
        for (auto e : v)
        {
            cout << e << " ";
        }
        cout << endl;

        // 正確刪除方法
        auto it = v.begin();
        while (it != v.end())
        {
            if (*it % 2 == 0)
            {
                it = v.erase(it);  // 接收erase返回值
            }
            else
            {
                ++it;
            }
        }

        cout << "刪除后: ";
        for (auto e : v)
        {
            cout << e << " ";
        }
        cout << endl;
    }

    // 測試resize操作
    void test_vector5()
    {
        cout << "\n測試resize操作:" << endl;
        bit::vector<int> v;
        v.push_back(1);
        v.push_back(2);
        v.push_back(2);
        v.push_back(3);
        v.push_back(4);
        v.push_back(5);
        v.push_back(6);
        
        cout << "原始vector: ";
        for (auto e : v)
        {
            cout << e << " ";
        }
        cout << endl;

        v.resize(3);  // 縮小
        cout << "resize(3): ";
        for (auto e : v)
        {
            cout << e << " ";
        }
        cout << endl;

        v.resize(20, 5);  // 擴(kuò)大并填充
        cout << "resize(20, 5): ";
        for (auto e : v)
        {
            cout << e << " ";
        }
        cout << endl;
    }

    // 測試拷貝構(gòu)造和賦值
    void test_vector6()
    {
        cout << "\n測試拷貝構(gòu)造和賦值:" << endl;
        bit::vector<int> v1;
        v1.push_back(1);
        v1.push_back(2);
        v1.push_back(2);
        v1.push_back(3);
        v1.push_back(4);
        v1.push_back(5);
        v1.push_back(6);
        
        cout << "v1: ";
        for (auto e : v1)
        {
            cout << e << " ";
        }
        cout << endl;

        // 拷貝構(gòu)造
        bit::vector<int> v2(v1);
        cout << "v2(拷貝v1): ";
        for (auto e : v2)
        {
            cout << e << " ";
        }
        cout << endl;

        // 賦值操作
        bit::vector<int> v3 = {10, 20, 30, 40};
        v1 = v3;
        cout << "v1(賦值后): ";
        for (auto e : v1)
        {
            cout << e << " ";
        }
        cout << endl;

        // 指定大小構(gòu)造
        bit::vector<int> v4(10, 1);
        cout << "v4(10個1): ";
        for (auto e : v4)
        {
            cout << e << " ";
        }
        cout << endl;

        bit::vector<char> v5(10, 'x');
        cout << "v5(10個x): ";
        for (auto e : v5)
        {
            cout << e << " ";
        }
        cout << endl;
    }

    // 測試string類型vector
    void test_vector7()
    {
        cout << "\n測試string類型vector:" << endl;
        bit::vector<string> v1;
        v1.push_back("111111111111111111111111");
        v1.push_back("222222222222222222222222");
        v1.push_back("333333333333333333333333");
        v1.push_back("444444444444444444444444");
        v1.push_back("555555555555555555555555");
        
        for (auto& e : v1)
        {
            cout << e << " ";
        }
        cout << endl;
    }
}

int main()
{
    bit::test_vector1();
    bit::test_vector2();
    bit::test_vector3();
    bit::test_vector4();
    bit::test_vector5();
    bit::test_vector6();
    bit::test_vector7();

    return 0;
}

C++ vector基于動態(tài)數(shù)組實(shí)現(xiàn),通過三個指針管理內(nèi)存。核心風(fēng)險是迭代器失效:insert可能擴(kuò)容使所有迭代器失效;erase使被刪位置后迭代器失效,必須通過it=erase(it)接收返回值。采用2倍擴(kuò)容策略,現(xiàn)代寫法通過swap實(shí)現(xiàn)安全拷貝。連續(xù)存儲支持高效隨機(jī)訪問,但需警惕迭代器失效這一主要陷阱。

總結(jié)

到此這篇關(guān)于C++ vector容器底層深度剖析與模擬實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)C++ vector容器底層內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

固镇县| 鄂托克前旗| 高平市| 湄潭县| 那曲县| 彭水| 天峨县| 高碑店市| 云浮市| 万载县| 广安市| 理塘县| 红原县| 兴宁市| 红河县| 岗巴县| 逊克县| 文登市| 博兴县| 八宿县| 平湖市| 天等县| 万州区| 海宁市| 抚松县| 舟山市| 前郭尔| 江源县| 溆浦县| 桦南县| 忻州市| 淮滨县| 黄浦区| 乌海市| 河东区| 马山县| 罗源县| 西平县| 云南省| 峨眉山市| 汾西县|