欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C++之vector剖析及模擬實(shí)現(xiàn)方式

 更新時(shí)間:2025年09月18日 09:31:55   作者:一枝小雨  
文章詳解C++ vector實(shí)現(xiàn),涵蓋三個(gè)指針管理動(dòng)態(tài)數(shù)組、容量擴(kuò)容機(jī)制、元素增刪操作及深拷貝原理,強(qiáng)調(diào)迭代器安全性和memcpy對(duì)自定義類型的風(fēng)險(xiǎn),提供使用示例與注意事項(xiàng)

1.0 std 庫 vector 源碼

官方文檔:vector

成員變量

template<class T>
class vector
{
public:
        typedef T* iterator;

private:
        iterator _start;
        iterator _finish;
        iterator _endofstorage;
};

1.1 vector 類的基本結(jié)構(gòu)與迭代器

類定義與成員變量

template<class T>
class vector
{
public:
    typedef T* iterator;              // 普通迭代器類型
    typedef const T* const_iterator;  // const迭代器類型
    
private:
    iterator _start;         // 指向數(shù)組首元素
    iterator _finish;        // 指向最后一個(gè)元素的下一個(gè)位置
    iterator _endofstorage;  // 指向存儲(chǔ)空間末尾的下一個(gè)位置
};

vector 使用三個(gè)指針來管理動(dòng)態(tài)數(shù)組:

  • _start:指向數(shù)組的第一個(gè)元素
  • _finish:指向最后一個(gè)元素之后的位置(即當(dāng)前元素?cái)?shù)量的末尾)
  • _endofstorage:指向已分配內(nèi)存的末尾之后的位置(即當(dāng)前容量的末尾)

構(gòu)造函數(shù)與析構(gòu)函數(shù)

// 默認(rèn)構(gòu)造函數(shù)
vector()
    :_start(nullptr)
    ,_finish(nullptr)
    ,_endofstorage(nullptr)
{}

// 析構(gòu)函數(shù)
~vector()
{
    delete[] _start;  // 釋放動(dòng)態(tài)分配的內(nèi)存
    _start = _finish = _endofstorage = nullptr;  // 指針置空
}
  • 默認(rèn)構(gòu)造函數(shù)初始化所有指針為 nullptr
  • 析構(gòu)函數(shù)釋放動(dòng)態(tài)分配的內(nèi)存并重置所有指針

迭代器訪問方法

// 普通正向迭代器
iterator begin() { return _start; }
iterator end() { return _finish; }

// 只讀正向迭代器
const_iterator begin() const { return _start; }
const_iterator end() const { return _finish; }
  • 提供迭代器訪問方法,使 vector 支持范圍 for 循環(huán)和標(biāo)準(zhǔn)庫算法
  • const 版本確保 const 對(duì)象只能進(jìn)行只讀訪問

1.2 容量管理

容量查詢方法

// 獲取元素?cái)?shù)量
size_t size() const { return _finish - _start; }

// 獲取當(dāng)前容量
size_t capacity() const { return _endofstorage - _start; }
  • size() 返回當(dāng)前元素?cái)?shù)量
  • capacity() 返回當(dāng)前分配的內(nèi)存容量

擴(kuò)容機(jī)制

// 擴(kuò)容方法
void reserve(size_t n)
{
    size_t sz = size();  // 提前計(jì)算當(dāng)前大小
    if (n > capacity())
    {
        T* tmp = new T[n];  // 分配新內(nèi)存
        if (_start)  // 防止第一次分配內(nèi)存時(shí) memcpy 出錯(cuò)
        {
            // 這里使用 memcpy 是有問題的,只能對(duì)內(nèi)置類型
            // 的vector進(jìn)行擴(kuò)容,具體問題和解決方案在
            // 后續(xù)“memcpy:更深一層次的深淺拷貝問題”
            memcpy(tmp, _start, sizeof(T) * sz);  // 拷貝數(shù)據(jù)
            delete[] _start;  // 釋放舊內(nèi)存
        }
        _start = tmp;
        _finish = tmp + sz;
        _endofstorage = tmp + n;
    }
}
  • reserve 方法用于預(yù)分配內(nèi)存,避免多次重新分配
  • 需要提前計(jì)算 size(),因?yàn)橹匦路峙浜?_start 會(huì)改變
  • 注意:使用 memcpy 只能對(duì)內(nèi)置類型進(jìn)行拷貝,對(duì)于自定義類型會(huì)有問題

元素訪問方法

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

// const 版本下標(biāo)運(yùn)算符
const T& operator[](size_t i) const
{
    assert(i < size());  // 越界檢查
    return _start[i];
}
  • 提供類似數(shù)組的隨機(jī)訪問功能
  • 包含越界檢查,提高代碼安全性

resize

/* resize */
// val不能給0,因?yàn)椴恢繲的類型,所以給一個(gè)T的缺省值
void resize(size_t n, const T& val = T())
{
        // 縮小size
        if (n < size())
                _finish = _start + n;
        else // 增大size
        {
                // 假如需要擴(kuò)容
                if (n > capacity())
                {
                        reserve(n);
                }

                while (_finish < _start + n)
                {
                        *_finish = val;
                        ++_finish;
                }
        }
}
  • 可以增大或減小 vector 的大小
  • 增大時(shí)用指定值填充新元素(默認(rèn)為 T 類型的默認(rèn)值)
  • 縮小時(shí)只是調(diào)整 _finish 指針,不釋放內(nèi)存

1.3 添加與刪除元素

push_back

// 尾插元素
void push_back(const T& x)
{
    // 空間不足時(shí)擴(kuò)容
    if (_finish == _endofstorage)
    {
        size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;
        reserve(newcapacity);
    }
    
    *_finish = x;  // 在末尾位置添加元素
    ++_finish;     // 更新末尾指針
}

// 也可以直接借助insert完成尾插
void push_back(const T& x) { insert(_finish, x); }
  • 當(dāng)容量不足時(shí)自動(dòng)擴(kuò)容(通常翻倍)
  • 在尾部添加元素并更新指針

insert

// pos位置插入
void insert(iterator pos, const T& x)
{
    assert(pos <= _finish);  // 檢查位置有效性
    
    // 空間不夠就增容
    if (_finish == _endofstorage)
    {
        // 記下pos相對(duì)于_start的位置
        size_t n = pos - _start;
        size_t newcapacity = capacity() == 0 ? 2 : capacity() * 2;
        reserve(newcapacity);
        // 空間增容導(dǎo)致原pos迭代器失效,更新迭代器位置
        pos = _start + n;
    }
    
    // 后移元素
    iterator end = _finish - 1;
    while (end >= pos)  // 依次把pos及pos后面的數(shù)據(jù)往后挪1位
    {
        *(end + 1) = *end;
        --end;
    }
    
    *pos = x;    // 插入新元素
    ++_finish;   // 更新末尾指針
}
  • 插入操作需要移動(dòng)后續(xù)元素,時(shí)間復(fù)雜度為 O(n)
  • 擴(kuò)容會(huì)導(dǎo)致迭代器失效,需要重新計(jì)算位置

erase

// 刪除指定位置元素
iterator erase(iterator pos)
{
    assert(pos < _finish);  // 檢查位置有效性
    
    iterator it = pos;
    while (it < _finish)  // 將后續(xù)元素前移
    {
        *it = *(it + 1);
        ++it;
    }
    
    --_finish;  // 更新末尾指針
    return pos;  // 返回刪除后該位置的迭代器
}

// 尾刪
void pop_back() { erase(_finish - 1); }
  • 刪除操作需要移動(dòng)后續(xù)元素,時(shí)間復(fù)雜度為 O(n)
  • 返回刪除后位置的迭代器,便于連續(xù)刪除操作

1.4 拷貝構(gòu)造與賦值重載

拷貝構(gòu)造函數(shù)

/* 拷貝構(gòu)造函數(shù) */
vector(const vector<T>& v)
{
        _start = new T[v.capacity()];
        _finish = _start;
        _endofstorage = _start + v.capacity();
        // 拷貝數(shù)據(jù)
        for (size_t i = 0; i < v.size(); ++i)
        {
                *_finish = v[i];
                ++_finish;
        }
}

更簡(jiǎn)潔的寫法:

/* 拷貝構(gòu)造函數(shù)(更簡(jiǎn)潔的寫法) */
vector(const vector<T>& v)
        :_start(nullptr)
        ,_finish(nullptr)
        ,_endofstorage(nullptr)
{
        reserve(v.capacity());        // 直接把空間開好,避免增容
        for (const auto& e : v)        // 把 v 的數(shù)據(jù)直接一個(gè)個(gè)push_back進(jìn)去
                push_back(e);
}
  • 實(shí)現(xiàn)深拷貝,避免多個(gè) vector 共享同一內(nèi)存
  • 先預(yù)分配足夠空間,然后逐個(gè)拷貝元素

賦值重載

/* 賦值重載 */
vector<T>& operator=(const vector<T>& v)
{
        if (this != &v)        // 防止自己賦值給自己
        {
                delete[] _start;
                _start = new T[v.capacity()];
                memcpy(_start, v._start, sizeof(T) * v.size());
                _finish = _start + v.size();
                _endofstorage = _start + v.capacity();
        }
        return *this;
}

賦值重載更簡(jiǎn)潔的寫法:

/* 賦值重載更簡(jiǎn)潔的寫法(現(xiàn)代寫法) */
vector<T>& operator=(vector<T> v)
{
        swap(v);
        return *this;
}
  • 使用"拷貝-交換"技術(shù)實(shí)現(xiàn)賦值運(yùn)算符
  • 參數(shù)通過值傳遞自動(dòng)調(diào)用拷貝構(gòu)造函數(shù)
  • 交換內(nèi)容后,臨時(shí)對(duì)象 v 在函數(shù)結(jié)束時(shí)自動(dòng)析構(gòu)

深淺拷貝問題

為什么我們需要深拷貝?

/* 深淺拷貝問題 */
void test_vector4()
{
        vector<int> v1;
        v1.push_back(1);
        v1.push_back(2);
        v1.push_back(3);
        v1.push_back(4);

        // 如果我們自己沒有實(shí)現(xiàn)深拷貝的拷貝構(gòu)造,就會(huì)發(fā)生和string類一樣的淺拷貝問題
        // 兩個(gè)vector對(duì)象的指針指向同一塊空間,最后析構(gòu)時(shí)同一塊空間被重復(fù)釋放,發(fā)生了錯(cuò)誤
        // 所以我們需要自己實(shí)現(xiàn)深拷貝
        vector<int> v2(v1);
        for (size_t i = 0; i < v1.size(); ++i)
        {
                cout << v2[i] << " ";
        }
        cout << endl;

        // 賦值同理
        vector<int> v3;
        v3.push_back(10);
        v3.push_back(20);
        v3.push_back(30);
        v3.push_back(40);

        v1 = v3;
        print_vector(v1);
        for (auto e : v1)
        {
                cout << e << " ";
        }
        cout << endl;
}

1.5 memcpy導(dǎo)致的更深一層次的深淺拷貝問題

受篇幅限制,這里給出文章鏈接:C++ memcpy導(dǎo)致的深拷貝問題

1.6 使用示例

遍歷與修改

void test_vector1()
{
    vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);

    // 使用迭代器遍歷和修改
    vector<int>::iterator it = v.begin();
    while (it != v.end())
    {
        *it += 1;
        cout << *it << " ";
        ++it;
    }
    cout << endl;

    // 范圍for循環(huán)
    for (auto& e : v)
    {
        e -= 1;
        cout << e << " ";
    }
    cout << endl;

    // 下標(biāo)訪問
    for (size_t i = 0; i < v.size(); ++i)
    {
        cout << v[i] << " ";
    }
    cout << endl;
}

插入與刪除

void test_vector2()
{
    vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(5);
    v.push_back(6);

    v.insert(v.begin(), 0);  // 在開頭插入0

    // 刪除所有偶數(shù)
    vector<int>::iterator it = v.begin();
    while (it != v.end())
    {
        if (*it % 2 == 0)
        {
            it = v.erase(it);  // 刪除元素并更新迭代器
        }
        else
        {
            ++it;
        }
    }
}

總結(jié)

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • C語言中函數(shù)與指針的應(yīng)用總結(jié)

    C語言中函數(shù)與指針的應(yīng)用總結(jié)

    本篇文章是對(duì)C語言中函數(shù)與指針的應(yīng)用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • C++用boost.signal實(shí)現(xiàn)多播委托

    C++用boost.signal實(shí)現(xiàn)多播委托

    這篇文章介紹了C++用boost.signal實(shí)現(xiàn)多播委托的方法,文中通過示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-06-06
  • C++實(shí)現(xiàn)地鐵自動(dòng)售票系統(tǒng)程序設(shè)計(jì)

    C++實(shí)現(xiàn)地鐵自動(dòng)售票系統(tǒng)程序設(shè)計(jì)

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)地鐵自動(dòng)售票系統(tǒng)程序設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • C語言函數(shù)多個(gè)返回值方式

    C語言函數(shù)多個(gè)返回值方式

    這篇文章主要介紹了C語言函數(shù)多個(gè)返回值方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 詳解C語言之預(yù)處理(上)

    詳解C語言之預(yù)處理(上)

    這篇文章主要介紹了C語言程序的預(yù)處理,小編覺得這篇文章寫的還不錯(cuò),需要的朋友可以參考下,希望能夠給你帶來幫助
    2021-11-11
  • C語言詳細(xì)解析有符號(hào)數(shù)與無符號(hào)數(shù)的表示

    C語言詳細(xì)解析有符號(hào)數(shù)與無符號(hào)數(shù)的表示

    我們知道,在C語言中存在無符號(hào)數(shù)和有符號(hào)數(shù),但是對(duì)于計(jì)算機(jī)而言,其本身并不區(qū)別有符號(hào)數(shù)和無符號(hào)數(shù),因?yàn)樵谟?jì)算機(jī)里面都是O或者1,但是在我們的實(shí)際使用中有時(shí)候需要使用有符號(hào)數(shù)來表示一個(gè)整數(shù),因此我們規(guī)定,當(dāng)最高位為1的時(shí),表示為負(fù)數(shù),最高位為0時(shí),表示為正數(shù)
    2022-04-04
  • C語言中6組指針和自增運(yùn)算符結(jié)合方式的運(yùn)算順序問題

    C語言中6組指針和自增運(yùn)算符結(jié)合方式的運(yùn)算順序問題

    本文通過代碼實(shí)現(xiàn)分析了6種組合:* p++,(* p)++,* (p++),++* p,++( * p), * (++p),需要的朋友可以參考下
    2015-07-07
  • 剖析c/c++的findcontours崩潰完美解決方案

    剖析c/c++的findcontours崩潰完美解決方案

    許多在Windows平臺(tái)上使用OpenCV的開發(fā)者可能會(huì)在使用findContours 函數(shù)時(shí),遇到令人頭疼的程序崩潰問題,本文將深入剖析此問題的潛在原因,并提供一個(gè)更可靠的定制化實(shí)現(xiàn)方案,感興趣的朋友一起看看吧
    2025-05-05
  • 淺談C++反向迭代器的設(shè)計(jì)

    淺談C++反向迭代器的設(shè)計(jì)

    本文主要介紹了淺談C++反向迭代器的設(shè)計(jì),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • c語言沒有try catch的替代方案

    c語言沒有try catch的替代方案

    這篇文章主要介紹了c語言沒有try catch的替代方案,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-06-06

最新評(píng)論