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

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

 更新時間:2025年09月18日 09:31:55   作者:一枝小雨  
文章詳解C++ vector實現(xiàn),涵蓋三個指針管理動態(tài)數(shù)組、容量擴容機制、元素增刪操作及深拷貝原理,強調(diào)迭代器安全性和memcpy對自定義類型的風(fē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;        // 指向最后一個元素的下一個位置
    iterator _endofstorage;  // 指向存儲空間末尾的下一個位置
};

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

  • _start:指向數(shù)組的第一個元素
  • _finish:指向最后一個元素之后的位置(即當(dāng)前元素數(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;  // 釋放動態(tài)分配的內(nèi)存
    _start = _finish = _endofstorage = nullptr;  // 指針置空
}
  • 默認(rèn)構(gòu)造函數(shù)初始化所有指針為 nullptr
  • 析構(gòu)函數(shù)釋放動態(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 對象只能進行只讀訪問

1.2 容量管理

容量查詢方法

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

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

擴容機制

// 擴容方法
void reserve(size_t n)
{
    size_t sz = size();  // 提前計算當(dāng)前大小
    if (n > capacity())
    {
        T* tmp = new T[n];  // 分配新內(nèi)存
        if (_start)  // 防止第一次分配內(nèi)存時 memcpy 出錯
        {
            // 這里使用 memcpy 是有問題的,只能對內(nèi)置類型
            // 的vector進行擴容,具體問題和解決方案在
            // 后續(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)存,避免多次重新分配
  • 需要提前計算 size(),因為重新分配后 _start 會改變
  • 注意:使用 memcpy 只能對內(nèi)置類型進行拷貝,對于自定義類型會有問題

元素訪問方法

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

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

resize

/* resize */
// val不能給0,因為不知道T的類型,所以給一個T的缺省值
void resize(size_t n, const T& val = T())
{
        // 縮小size
        if (n < size())
                _finish = _start + n;
        else // 增大size
        {
                // 假如需要擴容
                if (n > capacity())
                {
                        reserve(n);
                }

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

1.3 添加與刪除元素

push_back

// 尾插元素
void push_back(const T& x)
{
    // 空間不足時擴容
    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)容量不足時自動擴容(通常翻倍)
  • 在尾部添加元素并更新指針

insert

// pos位置插入
void insert(iterator pos, const T& x)
{
    assert(pos <= _finish);  // 檢查位置有效性
    
    // 空間不夠就增容
    if (_finish == _endofstorage)
    {
        // 記下pos相對于_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;   // 更新末尾指針
}
  • 插入操作需要移動后續(xù)元素,時間復(fù)雜度為 O(n)
  • 擴容會導(dǎo)致迭代器失效,需要重新計算位置

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); }
  • 刪除操作需要移動后續(xù)元素,時間復(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;
        }
}

更簡潔的寫法:

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

賦值重載

/* 賦值重載 */
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;
}

賦值重載更簡潔的寫法:

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

深淺拷貝問題

為什么我們需要深拷貝?

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

        // 如果我們自己沒有實現(xiàn)深拷貝的拷貝構(gòu)造,就會發(fā)生和string類一樣的淺拷貝問題
        // 兩個vector對象的指針指向同一塊空間,最后析構(gòu)時同一塊空間被重復(fù)釋放,發(fā)生了錯誤
        // 所以我們需要自己實現(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é)

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

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

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

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

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

    C++使用OpenCV進行物體識別與檢測的三種方法

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

    C++線程安全的隊列你了解嘛

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

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

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

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

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

最新評論

廊坊市| 铜鼓县| 称多县| 逊克县| 三明市| 东乌| 乐都县| 嘉义县| 丽水市| 平阴县| 西畴县| 长宁县| 厦门市| 湘潭市| 田阳县| 蒙阴县| 红河县| 得荣县| 固安县| 岢岚县| 清远市| 无棣县| 金华市| 淮安市| 阳新县| 宣武区| 嵊泗县| 双城市| 太湖县| 寿宁县| 澄江县| 三江| 紫金县| 呈贡县| 皋兰县| 霍山县| 繁峙县| 罗山县| 沭阳县| 定日县| 高碑店市|