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

C++中的list模擬實現(xiàn)解讀

 更新時間:2025年09月18日 09:02:01   作者:一枝小雨  
文章詳解C++ list模擬實現(xiàn),采用雙向循環(huán)鏈表結(jié)構(gòu),通過迭代器封裝與運算符重載實現(xiàn)容器功能,涵蓋構(gòu)造、拷貝、內(nèi)存管理及異常安全等關(guān)鍵點,并討論了測試與改進方向,如移動語義和STL兼容性

list 模擬實現(xiàn)詳解

1. 基本框架與節(jié)點結(jié)構(gòu)

list的底層實現(xiàn)通常采用帶頭雙向循環(huán)鏈表,每個節(jié)點包含指向前后節(jié)點的指針和數(shù)據(jù)域。

namespace practice_list
{
    template<class T>
    struct __list_node
    {
        __list_node<T>* _next;    // 指向下一個節(jié)點的指針
        __list_node<T>* _prev;    // 指向前一個節(jié)點的指針
        T _data;                  // 存儲的數(shù)據(jù)

        // 節(jié)點構(gòu)造函數(shù),使用默認(rèn)參數(shù)初始化
        __list_node(const T& x = T())
            : _data(x)           // 初始化數(shù)據(jù)域
            , _next(nullptr)     // 初始化next指針
            , _prev(nullptr)     // 初始化prev指針
        {}
    };
}

關(guān)鍵點說明:

  • 使用模板類實現(xiàn)泛型編程,支持任何數(shù)據(jù)類型
  • 節(jié)點包含前后指針,實現(xiàn)雙向鏈表結(jié)構(gòu)
  • 構(gòu)造函數(shù)使用默認(rèn)參數(shù),方便創(chuàng)建頭節(jié)點和數(shù)據(jù)節(jié)點

2. 迭代器初步實現(xiàn)

迭代器是讓鏈表能夠像容器一樣被遍歷的關(guān)鍵,它封裝了節(jié)點指針并重載了相關(guān)運算符。

2.1 簡單迭代器實現(xiàn)

template<class T>
struct __list_iterator
{
    typedef __list_node<T> Node;
    Node* _node;  // 封裝節(jié)點指針

    // 構(gòu)造函數(shù),通過節(jié)點指針初始化迭代器
    __list_iterator(Node* node)
        :_node(node)
    {}

    // 解引用操作符重載,返回節(jié)點數(shù)據(jù)的引用
    T& operator*()
    {
        return _node->_data;
    }

    // 前置++操作符重載,移動到下一個節(jié)點
    __list_iterator<T>& operator++()
    {
        _node = _node->_next;
        return *this;
    }

    // 不等于操作符重載,用于比較兩個迭代器
    bool operator!=(const __list_iterator<T>& it)
    {
        return _node != it._node;
    }
};

關(guān)鍵點說明:

  • 迭代器本質(zhì)上是對節(jié)點指針的封裝
  • 通過重載運算符實現(xiàn)指針-like的行為
  • operator*返回數(shù)據(jù)引用,使我們可以通過迭代器修改數(shù)據(jù)
  • operator++讓迭代器移動到下一個節(jié)點
  • operator!=用于比較迭代器是否指向相同節(jié)點

3. 基礎(chǔ)list類實現(xiàn)

3.1 類定義與迭代器類型聲明

template<class T>
class list
{
    typedef __list_node<T> Node;
public:
    // 聲明迭代器類型
    typedef __list_iterator<T> iterator;
    
    // 獲取指向第一個元素的迭代器
    iterator begin()
    {
        return iterator(_head->_next);  // 匿名對象寫法
    }
    
    // 獲取尾后迭代器(指向頭節(jié)點)
    iterator end()
    {
        return iterator(_head);  // 匿名對象寫法
    }
    
    // 構(gòu)造函數(shù),初始化帶頭雙向循環(huán)鏈表
    list()
    {
        _head = new Node;      // 創(chuàng)建頭節(jié)點
        _head->_next = _head;  // 頭節(jié)點的next指向自己
        _head->_prev = _head;  // 頭節(jié)點的prev指向自己
    }
    
    // 尾插函數(shù)
    void push_back(const T& x)
    {
        Node* tail = _head->_prev;  // 找到當(dāng)前尾節(jié)點
        Node* newnode = new Node(x); // 創(chuàng)建新節(jié)點
        
        // 鏈接新節(jié)點與前一個節(jié)點(尾節(jié)點)
        tail->_next = newnode;
        newnode->_prev = tail;
        
        // 鏈接新節(jié)點與后一個節(jié)點(頭節(jié)點)
        newnode->_next = _head;
        _head->_prev = newnode;
    }

private:
    Node* _head;  // 頭節(jié)點指針
};

關(guān)鍵點說明:

  • list類維護一個頭節(jié)點指針_head
  • begin()返回第一個有效元素的迭代器(頭節(jié)點的下一個節(jié)點)
  • end()返回尾后迭代器(指向頭節(jié)點本身)
  • 構(gòu)造函數(shù)初始化一個空鏈表,頭節(jié)點指向自己
  • push_back()在鏈表尾部插入新節(jié)點

3.2 測試函數(shù)

void test_list1()
{
    list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);

    list<int>::iterator it = lt.begin();
    while (it != lt.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;
}

4. 完整迭代器實現(xiàn)

更完整的迭代器實現(xiàn)需要考慮const迭代器、前后移動等功能。

4.1 進階迭代器設(shè)計

// 使用三個模板參數(shù)支持普通迭代器和const迭代器
// T: 數(shù)據(jù)類型, Ref: 引用類型, Ptr: 指針類型
template<class T, class Ref, class Ptr>
struct __list_iterator
{
    typedef __list_node<T> Node;
    typedef __list_iterator<T, Ref, Ptr> Self;  // 自身類型別名
    Node* _node;

    __list_iterator(Node* node)
        :_node(node)
    {}

    // 解引用操作符,返回Ref類型(T&或const T&)
    Ref operator*()
    {
        return _node->_data;
    }

    // 前置++
    Self& operator++()
    {
        _node = _node->_next;
        return *this;
    }

    // 后置++(int參數(shù)用于區(qū)分前置和后置)
    Self operator++(int)
    {
        Self ret = _node;  // 保存當(dāng)前狀態(tài)
        ++(*this);         // 調(diào)用前置++
        return ret;        // 返回之前保存的狀態(tài)
    }

    // 前置--
    Self& operator--()
    {
        _node = _node->_prev;
        return *this;
    }

    // 后置--
    Self operator--(int)
    {
        Self ret = _node;
        --(*this);
        return ret;
    }

    // 不等于操作符
    bool operator!=(const Self& it)
    {
        return _node != it._node;
    }

    // 等于操作符
    bool operator==(const Self& it)
    {
        return !(_node != it._node);
    }

    // 箭頭操作符,用于訪問成員
    Ptr operator->()
    {
        return &(_node->_data);
    }
};

關(guān)鍵點說明:

  • 使用三個模板參數(shù)實現(xiàn)普通迭代器和const迭代器的統(tǒng)一實現(xiàn)
  • 添加了前后移動操作(++和--的前置和后置版本)
  • 實現(xiàn)了箭頭操作符,用于直接訪問成員變量
  • 使用Self類型別名簡化代碼編寫

5. 完整list類實現(xiàn)

5.1 類型定義與構(gòu)造函數(shù)

template<class T>
class list
{
    typedef __list_node<T> Node;
private:
    Node* _head;  // 頭節(jié)點指針
    
public:
    // 普通迭代器類型
    typedef __list_iterator<T, T&, T*> iterator;
    // const迭代器類型
    typedef __list_iterator<T, const T&, const T*> const_iterator;

    // 構(gòu)造函數(shù)
    list()
    {
        _head = new Node;
        _head->_next = _head;
        _head->_prev = _head;
    }
    
    // 析構(gòu)函數(shù)
    ~list(){
        clear();     // 清空所有節(jié)點
        delete _head;        // 刪除頭節(jié)點
        _head = nullptr;
    }
    
    // 獲取起始迭代器
    iterator begin()
    {
        return iterator(_head->_next);
    }
    
    // 獲取尾后迭代器
    iterator end()
    {
        return iterator(_head);
    }
    
    // 獲取const起始迭代器
    const_iterator begin() const
    {
        return const_iterator(_head->_next);
    }
    
    // 獲取const尾后迭代器
    const_iterator end() const
    {
        return const_iterator(_head);
    }
    
    

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

    // 拷貝構(gòu)造函數(shù)
    list(const list<T>& lt)
    {
        _head = new Node;
        _head->_next = _head;
        _head->_prev = _head;
        
        // 遍歷源鏈表,插入數(shù)據(jù)
        const_iterator it = lt.begin();
        while (it != lt.end())
        {
            push_back(*it);
            ++it;
        }
        
        // 使用范圍for,更簡潔
        /*for (auto e : lt)
        {
                push_back(*it);
        }*/
    }
    
    /* 賦值重載 */
    /*list<T>& operator=(const list<T>& lt)
    {
            if (this != &lt)
            {
                    clear();
                    for (auto e : lt)
                    {
                            push_back(e);
                    }
            }
            else
                    return *this;
    }*/
    // 賦值運算符(簡潔寫法)
    list<T>& operator=(list<T> lt)  // 傳參調(diào)用拷貝構(gòu)造
    {
        swap(_head, lt._head);  // 交換頭指針
        return *this;           // 返回當(dāng)前對象
    }

5.3 元素訪問與修改函數(shù)

    // 尾插
    void push_back(const T& x)
    {
        /*
        Node* tail = _head->_prev;
        Node* newnode = new Node(x);
        // 鏈接newnode與newnode前一個節(jié)點tail
        tail->_next = newnode;
        newnode->_prev = tail;
        // 鏈接newnode與newnod后一個節(jié)點"頭節(jié)點"
        newnode->_next = _head;
        _head->_prev = newnode;
        */
        
        insert(end(), x);  // 在end()前插入
    }
    
    // 尾刪
    void pop_back()
    {
        /*Node* tail = _head->_prev;
        Node* newtail = tail->_prev;
        delete[] tail;
        _head->_prev = newtail;
        newtail->_next = _head;*/

        erase(--end());
        // erase(iterator(_head->_prev)); 這種寫法也可以
    }
    
    // 頭插
    void push_front(const T& x)
    {
        insert(begin(), x);  // 在begin()前插入
    }
    
    // 頭刪
    void pop_front()
    {
        erase(begin());  // 刪除第一個元素
    }
    
    // 在指定位置前插入
    void insert(iterator pos, const T& x)
    {
        Node* cur = pos._node;    // 當(dāng)前節(jié)點
        Node* prev = cur->_prev;  // 前一個節(jié)點
        Node* newnode = new Node(x);  // 新節(jié)點
        
        // 鏈接新節(jié)點與前一個節(jié)點
        prev->_next = newnode;
        newnode->_prev = prev;
        
        // 鏈接新節(jié)點與當(dāng)前節(jié)點
        newnode->_next = cur;
        cur->_prev = newnode;
    }
    
    // 刪除指定位置元素
    void erase(iterator pos)
    {
        assert(pos != end());  // 不能刪除頭節(jié)點
        
        Node* cur = pos._node;
        Node* next = cur->_next;
        Node* prev = cur->_prev;
        
        delete cur;  // 釋放節(jié)點內(nèi)存
        
        // 重新鏈接前后節(jié)點
        next->_prev = prev;
        prev->_next = next;
    }
    
    // 清空鏈表(保留頭節(jié)點)
    void clear()
    {
        iterator it = begin();
        while (it != end())
        {
        erase(it++);  // 使用后置++避免迭代器失效
        }
    }

};

6. 測試代碼與特殊用例

6.1 基本功能測試

void test_list1()
{
    list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);

    list<int>::iterator it = lt.begin();
    while (it != lt.end())
    {
        cout << *it << " ";
        ++it;
    }
    cout << endl;
}

6.2 結(jié)構(gòu)體訪問測試

struct Date
{
    int _year = 0;
    int _month = 1;
    int _day = 1;
};

void test_list2()
{
    list<Date> lt;
    lt.push_back(Date());
    lt.push_back(Date());

    list<Date>::iterator it = lt.begin();
    while (it != lt.end())
    {
        cout << it->_year << "-" << it->_month << "-" << it->_day << endl;
        ++it;
    }
    cout << endl;
}

關(guān)鍵點說明:

  • it->等價于it.operator->(),返回Date*
  • 編譯器特殊處理了it->member,使其等價于(it.operator->())->member
  • 這種語法糖提高了代碼的可讀性

6.3 const迭代器測試

void print_list(const list<int>& lt)
{
    list<int>::const_iterator it = lt.begin();
    while (it != lt.end())
    {
        // *it = 1;  // 錯誤:不能修改const引用指向的值
        cout << *it << " ";
        ++it;
    }
    cout << endl;
}

6.4 拷貝構(gòu)造與賦值測試

void test_list4()
{
    list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);

    list<int> lt2(lt);  // 測試拷貝構(gòu)造函數(shù)
    print_list(lt2);
}

void test_list5()
{
    list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);

    list<int> lt2;
    lt2.push_back(10);
    lt2.push_back(20);
    lt2.push_back(30);
    lt2.push_back(40);
    
    lt = lt2;  // 測試賦值運算符
    print_list(lt);
}

7. 補充說明與注意事項

7.1 迭代器設(shè)計的關(guān)鍵點

  • 封裝指針行為:迭代器封裝了節(jié)點指針,使其能夠像指針一樣使用
  • 模板技巧:通過模板參數(shù)區(qū)分普通迭代器和const迭代器
  • 前后置運算符:正確實現(xiàn)++和--的前置和后置版本
  • 箭頭運算符:特殊處理->操作符以直接訪問成員

7.2 鏈表操作的關(guān)鍵點

  • 邊界處理:始終維護雙向循環(huán)鏈表的完整性
  • 異常安全:在修改鏈表結(jié)構(gòu)前分配資源,確保異常安全
  • 迭代器失效:插入和刪除操作可能導(dǎo)致迭代器失效,需要特別注意
  • 內(nèi)存管理:確保所有動態(tài)分配的節(jié)點都被正確釋放

7.3 可行的改進點

  • 異常處理:可以添加異常處理機制增強魯棒性
  • 性能優(yōu)化:可以考慮添加移動語義支持(C++11)
  • 更多容器操作:實現(xiàn)如resize(), merge(), sort()等常用操作
  • 迭代器萃?。禾砑拥魈匦灾С?,與STL算法更好地配合

總結(jié)

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

相關(guān)文章

  • C語言實現(xiàn)學(xué)生考勤系統(tǒng)

    C語言實現(xiàn)學(xué)生考勤系統(tǒng)

    這篇文章主要為大家詳細介紹了C語言實現(xiàn)學(xué)生考勤系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 淺析VC++中的頭文件包含問題

    淺析VC++中的頭文件包含問題

    類中盡量采用指針或引用方式調(diào)用其它類,這樣就可以只聲明class xxx了。并且這也符合資源最優(yōu)利用,更利于使用多態(tài)
    2013-09-09
  • LintCode 堆化詳解及實例代碼

    LintCode 堆化詳解及實例代碼

    這篇文章主要介紹了LintCode 堆化詳解及實例代碼的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • C++淺析虛函數(shù)使用方法

    C++淺析虛函數(shù)使用方法

    對C++了解的人都應(yīng)該知道虛函數(shù)(Virtual Function)是通過一張?zhí)摵瘮?shù)表(Virtual Table)來實現(xiàn)的。簡稱為V-Table。本文就將詳細講講虛函數(shù)表的原理與使用,需要的可以參考一下
    2022-08-08
  • mysate中stat命令的實現(xiàn)方法

    mysate中stat命令的實現(xiàn)方法

    這篇文章主要介紹了mysate中stat命令的實現(xiàn)方法,stat作用:用來顯示文件的詳細信息,包括inode, atime, mtime, ctime,本文給大家介紹的非常詳細,需要的朋友可以參考下
    2022-10-10
  • 嵌入式項目使用C語言結(jié)構(gòu)體位段特性實現(xiàn)斷言宏校驗數(shù)據(jù)范圍有效性的方法

    嵌入式項目使用C語言結(jié)構(gòu)體位段特性實現(xiàn)斷言宏校驗數(shù)據(jù)范圍有效性的方法

    今天小編就為大家分享一篇關(guān)于嵌入式項目使用C語言結(jié)構(gòu)體位段特性實現(xiàn)斷言宏校驗數(shù)據(jù)范圍有效性的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • C語言讀寫配置文件的方法

    C語言讀寫配置文件的方法

    這篇文章主要介紹了C語言讀寫配置文件的方法,包括C語言讀寫ini配置文件所涉及的文件讀寫技巧,以及完整的源文件及頭文件實現(xiàn)方法,需要的朋友可以參考下
    2015-07-07
  • C++設(shè)計模式之迭代器模式(Iterator)

    C++設(shè)計模式之迭代器模式(Iterator)

    這篇文章主要為大家詳細介紹了C++設(shè)計模式之迭代器模式Iterator,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • 分享C++面試中string類的一種正確寫法

    分享C++面試中string類的一種正確寫法

    C++ 的一個常見面試題是讓你實現(xiàn)一個 String 類,限于時間,不可能要求具備 std::string 的功能,但至少要求能正確管理資源
    2013-11-11
  • C語言基礎(chǔ)指針詳解教程

    C語言基礎(chǔ)指針詳解教程

    此處對于指針做一些簡要的介紹,作者實屬初學(xué),寫博客也是作者學(xué)習(xí)的一個過程,難免文章中有內(nèi)容理解不到位或者有不當(dāng)之處,還請朋友們不吝指正,希望大家給予支持
    2021-11-11

最新評論