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

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

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

1 模板的使用說(shuō)明

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

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

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

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

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

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

2.1 vector的成員變量

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

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

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

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

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

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個(gè)0的vector
vector<int> v2(3, 10);    // 包含3個(gè)10的vector
vector<string> v3(2, "hello"); // 包含2個(gè)"hello"的vector

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

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

這個(gè)構(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());   // 從另一個(gè)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)代寫法通過(guò)創(chuàng)建臨時(shí)對(duì)象并交換資源,代碼簡(jiǎn)潔且異常安全~

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

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

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

2.4.1 reserve 開(kāi)空間

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,對(duì)于管理資源的類(如string)會(huì)導(dǎo)致淺拷貝問(wèn)題!

  • 重新計(jì)算_finish_end_of_storage指針

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

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

這里使用匿名對(duì)象做缺省參數(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 元素訪問(wèn)操作

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版本,支持讀寫訪問(wèn)只讀訪問(wèn)。

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時(shí)分配4個(gè)元素空間,否則每次擴(kuò)容為原來(lái)的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;
    }

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

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

擴(kuò)容后需要重新計(jì)算pos的位置,因?yàn)開(kāi)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迭代器失效問(wèn)題

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

3.1 insert失效問(wèn)題

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

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;  // 錯(cuò)誤!未定義行為
}

3.2 erase失效問(wèn)題

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

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());  // 刪除第一個(gè)元素
    
    // it失效了,不能訪問(wèn),訪問(wèn)結(jié)果未定義
    // cout << *it << endl;  // 錯(cuò)誤!
}

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返回下一個(gè)有效迭代器
        }
        else
        {
            ++it;
        }
    }
    
    // 錯(cuò)誤做法:直接遞增迭代器
    // auto it = v.begin();
    // while (it != v.end())
    // {
    //     if (*it % 2 == 0)
    //     {
    //         v.erase(it);  // erase后it失效
    //     }
    //     ++it;  // 錯(cuò)誤:對(duì)失效迭代器遞增
    // }
}

3.4 不同編譯器對(duì)迭代器失效的檢查

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

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

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

  • Linux的gcc編譯器檢查就會(huì)比較寬松

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刪除的迭代器如果是最后一個(gè)元素

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

3.7 string的迭代器失效

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

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;
        }

        // 交換兩個(gè)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;
        }

        // 獲取元素個(gè)數(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;
    }

    // 測(cè)試基本操作
    void test_vector1()
    {
        cout << "測(cè)試基本操作:" << 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]++;  // 修改第一個(gè)元素
        
        Print(v);
        
        // 范圍for遍歷
        for (auto e : v)
        {
            cout << e << " ";
        }
        cout << endl;
    }

    // 測(cè)試insert操作
    void test_vector2()
    {
        cout << "\n測(cè)試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);
    }

    // 測(cè)試erase操作
    void test_vector3()
    {
        cout << "\n測(cè)試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());  // 刪除第一個(gè)元素
        Print(v);

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

    // 測(cè)試刪除特定元素(刪除所有偶數(shù))
    void test_vector4()
    {
        cout << "\n測(cè)試刪除所有偶數(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;
    }

    // 測(cè)試resize操作
    void test_vector5()
    {
        cout << "\n測(cè)試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;
    }

    // 測(cè)試拷貝構(gòu)造和賦值
    void test_vector6()
    {
        cout << "\n測(cè)試拷貝構(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個(gè)1): ";
        for (auto e : v4)
        {
            cout << e << " ";
        }
        cout << endl;

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

    // 測(cè)試string類型vector
    void test_vector7()
    {
        cout << "\n測(cè)試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基于動(dòng)態(tài)數(shù)組實(shí)現(xiàn),通過(guò)三個(gè)指針管理內(nèi)存。核心風(fēng)險(xiǎn)是迭代器失效:insert可能擴(kuò)容使所有迭代器失效;erase使被刪位置后迭代器失效,必須通過(guò)it=erase(it)接收返回值。采用2倍擴(kuò)容策略,現(xiàn)代寫法通過(guò)swap實(shí)現(xiàn)安全拷貝。連續(xù)存儲(chǔ)支持高效隨機(jī)訪問(wèn),但需警惕迭代器失效這一主要陷阱。

總結(jié)

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

相關(guān)文章

最新評(píng)論

大港区| 四平市| 卓尼县| 丹阳市| 揭西县| 吴川市| 潮安县| 会昌县| 东台市| 芜湖市| 巨鹿县| 米易县| 江口县| 临邑县| 马公市| 宁晋县| 应城市| 宁晋县| 枝江市| 基隆市| 隆昌县| 天镇县| 阳江市| 崇信县| 墨江| 苗栗县| 泗阳县| 和田县| 洮南市| 探索| 仙游县| 忻城县| 阿坝县| 巩留县| 武平县| 蒙城县| 海盐县| 邹城市| 吉隆县| 富民县| 滕州市|