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

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 庫(kù) 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è)指針來(lái)管理動(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)存并重置所有指針

迭代器訪問(wèn)方法

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

// 只讀正向迭代器
const_iterator begin() const { return _start; }
const_iterator end() const { return _finish; }
  • 提供迭代器訪問(wèn)方法,使 vector 支持范圍 for 循環(huán)和標(biāo)準(zhǔn)庫(kù)算法
  • const 版本確保 const 對(duì)象只能進(jìn)行只讀訪問(wè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 是有問(wèn)題的,只能對(duì)內(nèi)置類型
            // 的vector進(jìn)行擴(kuò)容,具體問(wèn)題和解決方案在
            // 后續(xù)“memcpy:更深一層次的深淺拷貝問(wèn)題”
            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ì)有問(wèn)題

元素訪問(wèn)方法

// 下標(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ī)訪問(wèn)功能
  • 包含越界檢查,提高代碼安全性

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());        // 直接把空間開(kāi)好,避免增容
        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ù)通過(guò)值傳遞自動(dòng)調(diào)用拷貝構(gòu)造函數(shù)
  • 交換內(nèi)容后,臨時(shí)對(duì)象 v 在函數(shù)結(jié)束時(shí)自動(dòng)析構(gòu)

深淺拷貝問(wèn)題

為什么我們需要深拷貝?

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

        // 如果我們自己沒(méi)有實(shí)現(xiàn)深拷貝的拷貝構(gòu)造,就會(huì)發(fā)生和string類一樣的淺拷貝問(wèn)題
        // 兩個(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)致的更深一層次的深淺拷貝問(wèn)題

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

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)訪問(wèn)
    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);  // 在開(kāi)頭插入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ù)組來(lái)實(shí)現(xiàn)哈夫曼樹(shù)

    C++使用數(shù)組來(lái)實(shí)現(xiàn)哈夫曼樹(shù)

    給定N個(gè)權(quán)值作為N個(gè)葉子結(jié)點(diǎn),構(gòu)造一棵二叉樹(shù),若該樹(shù)的帶權(quán)路徑長(zhǎng)度達(dá)到最小,稱這樣的二叉樹(shù)為最優(yōu)二叉樹(shù),也稱為哈夫曼樹(shù)(Huffman?Tree)。哈夫曼樹(shù)是帶權(quán)路徑長(zhǎng)度最短的樹(shù),權(quán)值較大的結(jié)點(diǎn)離根較近
    2022-05-05
  • C語(yǔ)言使用libZPlay錄制聲音并寫到文件的方法

    C語(yǔ)言使用libZPlay錄制聲音并寫到文件的方法

    這篇文章主要介紹了C語(yǔ)言使用libZPlay錄制聲音并寫到文件的方法,實(shí)例分析了C語(yǔ)言操作音頻文件的相關(guān)技巧,需要的朋友可以參考下
    2015-06-06
  • 深入理解C++函數(shù)棧幀

    深入理解C++函數(shù)棧幀

    本文主要介紹了C++函數(shù)棧幀,詳細(xì)的介紹了C++函數(shù)棧幀的概念以及使用,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-07-07
  • C語(yǔ)言詳細(xì)講解指針數(shù)組的用法

    C語(yǔ)言詳細(xì)講解指針數(shù)組的用法

    在C語(yǔ)言和C++等語(yǔ)言中,數(shù)組元素全為指針變量的數(shù)組稱為指針數(shù)組,指針數(shù)組中的元素都必須具有相同的存儲(chǔ)類型、指向相同數(shù)據(jù)類型的指針變量。指針數(shù)組比較適合用來(lái)指向若干個(gè)字符串,使字符串處理更加方便、靈活
    2022-05-05
  • C語(yǔ)言由淺入深講解文件的操作下篇

    C語(yǔ)言由淺入深講解文件的操作下篇

    C語(yǔ)言具有操作文件的能力,比如打開(kāi)文件、讀取和追加數(shù)據(jù)、插入和刪除數(shù)據(jù)、關(guān)閉文件、刪除文件等。與其他編程語(yǔ)言相比,C語(yǔ)言文件操作的接口相當(dāng)簡(jiǎn)單和易學(xué)
    2022-04-04
  • 詳細(xì)總結(jié)C++的排序算法

    詳細(xì)總結(jié)C++的排序算法

    趁空閑時(shí)間,小編決定把C++的排序算法分析并總結(jié)下,以便溫故知新。也方便需要的朋友可以參考學(xué)習(xí)。
    2016-07-07
  • C++使用OpenCV進(jìn)行物體識(shí)別與檢測(cè)的三種方法

    C++使用OpenCV進(jìn)行物體識(shí)別與檢測(cè)的三種方法

    物體識(shí)別與檢測(cè)是計(jì)算機(jī)視覺(jué)中的核心任務(wù)之一,它被廣泛應(yīng)用于自動(dòng)駕駛、安防監(jiān)控、圖像分析等領(lǐng)域,通過(guò)物體檢測(cè)技術(shù),計(jì)算機(jī)能夠從圖像中識(shí)別出特定的物體或目標(biāo),本文將介紹如何使用 C++ 和 OpenCV 庫(kù)進(jìn)行物體識(shí)別與檢測(cè),需要的朋友可以參考下
    2025-04-04
  • C++線程安全的隊(duì)列你了解嘛

    C++線程安全的隊(duì)列你了解嘛

    這篇文章主要為大家詳細(xì)介紹了C++線程安全的隊(duì)列,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-03-03
  • C語(yǔ)言?動(dòng)態(tài)內(nèi)存管理全面解析

    C語(yǔ)言?動(dòng)態(tài)內(nèi)存管理全面解析

    動(dòng)態(tài)內(nèi)存是相對(duì)靜態(tài)內(nèi)存而言的。所謂動(dòng)態(tài)和靜態(tài)就是指內(nèi)存的分配方式。動(dòng)態(tài)內(nèi)存是指在堆上分配的內(nèi)存,而靜態(tài)內(nèi)存是指在棧上分配的內(nèi)存,本文帶你深入探究C語(yǔ)言中動(dòng)態(tài)內(nèi)存的管理
    2022-02-02
  • C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)算法之實(shí)現(xiàn)快速傅立葉變換

    C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)算法之實(shí)現(xiàn)快速傅立葉變換

    這篇文章主要介紹了C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)算法之實(shí)現(xiàn)快速傅立葉變換的相關(guān)資料,需要的朋友可以參考下
    2017-06-06

最新評(píng)論

昌都县| 内黄县| 罗甸县| 隆子县| 斗六市| 怀宁县| 卢氏县| 张北县| 洞口县| 资中县| 屏南县| 清河县| 台湾省| 论坛| 洞头县| 烟台市| 剑川县| 榆社县| 苗栗市| 贺兰县| 安泽县| 贵定县| 兴山县| 徐闻县| 子长县| 泗洪县| 赤峰市| 略阳县| 香格里拉县| 廊坊市| 子洲县| 阿克| 灵寿县| 正蓝旗| 柳江县| 唐山市| 临澧县| 稷山县| 莎车县| 莒南县| 五常市|