【C++】手写双向链表:list容器模拟实现

📌 相关专栏

很高兴你点开这篇文章✨

这里会持续更新更多有用的内容,关注我,一起慢慢变好呀

👍 点赞 ⭐ 收藏 💬 评论


文章目录

  • 前言
  • [1. 整体架构:命名空间与节点结构](#1. 整体架构:命名空间与节点结构)
    • [1.1 命名空间封装](#1.1 命名空间封装)
    • [1.2 链表节点结构体](#1.2 链表节点结构体)
    • [1.3 节点关系图](#1.3 节点关系图)
  • [2. 哨兵位头节点与循环链表设计](#2. 哨兵位头节点与循环链表设计)
    • [2.1 什么是哨兵位头节点?](#2.1 什么是哨兵位头节点?)
    • [2.2 空链表初始化](#2.2 空链表初始化)
  • [3. 迭代器设计:三模板参数复用](#3. 迭代器设计:三模板参数复用)
    • [3.1 为什么迭代器需要封装?](#3.1 为什么迭代器需要封装?)
    • [3.2 三模板参数设计(核心亮点)](#3.2 三模板参数设计(核心亮点))
    • [3.3 为什么这样设计?](#3.3 为什么这样设计?)
  • [4. 迭代器运算符重载(模拟指针行为)](#4. 迭代器运算符重载(模拟指针行为))
    • [4.1 解引用 operator*](#4.1 解引用 operator*)
    • [4.2 箭头 operator->](#4.2 箭头 operator->)
    • [4.3 前置 ++ / 后置 ++](#4.3 前置 ++ / 后置 ++)
    • [4.4 前置 -- / 后置 --](#4.4 前置 -- / 后置 --)
    • [4.5 比较运算符](#4.5 比较运算符)
  • [5. list 类的主体框架与构造](#5. list 类的主体框架与构造)
    • [5.1 类成员变量](#5.1 类成员变量)
    • [5.2 默认构造](#5.2 默认构造)
    • [5.3 初始化列表构造](#5.3 初始化列表构造)
    • [5.4 迭代器区间构造(函数模板)](#5.4 迭代器区间构造(函数模板))
    • [5.5 析构函数](#5.5 析构函数)
  • [6. 增删操作:insert、erase 与复用](#6. 增删操作:insert、erase 与复用)
    • [6.1 insert:任意位置插入(O(1))](#6.1 insert:任意位置插入(O(1)))
    • [6.2 erase:任意位置删除(O(1))](#6.2 erase:任意位置删除(O(1)))
    • [6.3 复用:push_back、push_front、pop_back、pop_front](#6.3 复用:push_back、push_front、pop_back、pop_front)
    • [6.4 clear:清空所有数据节点](#6.4 clear:清空所有数据节点)
  • [7. 迭代器接口与 const 版本](#7. 迭代器接口与 const 版本)
  • [8. 完整测试用例](#8. 完整测试用例)
    • [test 1 :基础插入与遍历](#test 1 :基础插入与遍历)
    • [test 2 :头插尾插与头删尾删](#test 2 :头插尾插与头删尾删)
    • [test 3 :拷贝构造与 const 迭代器](#test 3 :拷贝构造与 const 迭代器)
    • [test 4 :insert、erase 与 clear](#test 4 :insert、erase 与 clear)
  • [9. 总结](#9. 总结)
  • 本文全部代码
    • [🐾 list.h](#🐾 list.h)
    • [🐾 Test.cpp](#🐾 Test.cpp)

前言

std::list 是 C++ 标准库中的双向链表容器。与 vector 不同,list 的元素在内存中不连续存储,而是通过指针链接。实现一个正确的 list 需要解决以下核心问题:

  • 节点结构:如何存储数据与前驱后继指针?
  • 哨兵位头节点:如何简化边界条件处理?
  • 迭代器设计:如何用类封装节点指针,模拟指针行为?
  • 普通/const 迭代器复用:如何用一套代码同时生成两种迭代器?

🐶 🐾 ✨ 🐾 🐶


1. 整体架构:命名空间与节点结构

1.1 命名空间封装

为避免与标准库 std::list 冲突,我们将实现放在自定义命名空间中:

cpp 复制代码
namespace QianYv      // 避免与 std::list 冲突
{
    // list 实现...
}

1.2 链表节点结构体

节点是链表的基本单元,包含前驱指针、后继指针和存储的数据:

cpp 复制代码
template<class T>
struct list_node
{
    list_node<T>* _prev;   // 前驱节点指针
    list_node<T>* _next;   // 后继节点指针
    T _data;               // 节点存储的数据

    // 构造函数:默认值初始化,指针置空
    list_node(const T& x = T())
        : _prev(nullptr)
        , _next(nullptr)
        , _data(x)
    {
    }
};

关于 T() 的解读:

  • 当 T 是 int 时,T() 就是 0
  • 当 T 是 string 时,T() 调用其默认构造函数
  • 这确保了无论是内置类型还是自定义类型,都能正确初始化

1.3 节点关系图

🐶 🐾 ✨ 🐾 🐶


2. 哨兵位头节点与循环链表设计

2.1 什么是哨兵位头节点?

哨兵位头节点是一个不存储有效数据的节点,它的作用是:

  • 简化插入删除:无需特殊判断是否为空链表
  • 统一边界条件:begin() 指向 _head->_next,end() 指向 _head
  • 实现循环结构:空链表时,_head->_prev = _head->_next = _head

2.2 空链表初始化

cpp 复制代码
void empty_init()
{
    _head = new Node;           // 创建哨兵头节点
    _head->_prev = _head;       // 前驱指向自己
    _head->_next = _head;       // 后继指向自己(形成自环)
    _size = 0;                  // 有效元素个数为 0
}

list()
{
    empty_init();               // 默认构造调用统一初始化
}

空链表结构:

🐶 🐾 ✨ 🐾 🐶


3. 迭代器设计:三模板参数复用

3.1 为什么迭代器需要封装?

list 的节点指针 node* 不能直接作为迭代器使用,因为:

  • 原生指针 ++ 操作是移动一个 sizeof(Node),而链表需要移动到 _next
  • 我们需要重载 ++、--、*、-> 等运算符来模拟指针行为

3.2 三模板参数设计(核心亮点)

cpp 复制代码
// 迭代器类:通过三个模板参数实现普通/const 迭代器复用
template<class T, class Ref, class Ptr>
struct list_iterator
{
    using Self = list_iterator<T, Ref, Ptr>;  // 自身类型别名
    using Node = list_node<T>;                // 节点类型别名

    Node* _node;  // 封装的节点指针

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

    // ... 运算符重载 ...
};

三模板参数的含义:

模板参数 普通迭代器 const 迭代器 作用
T T T 节点数据类型
Ref T& const T& operator* 返回类型
Ptr T* const T* operator-> 返回类型

3.3 为什么这样设计?

设计原理 :用一套迭代器代码,同时生成普通迭代器和 const 迭代器,避免重复写两份几乎相同的类。

cpp 复制代码
using iterator = list_iterator<T, T&, T*>;           // 普通迭代器
using const_iterator = list_iterator<T, const T&, const T*>;  // const 迭代器

🐶 🐾 ✨ 🐾 🐶


4. 迭代器运算符重载(模拟指针行为)

4.1 解引用 operator*

cpp 复制代码
Ref operator*()
{
    return _node->_data;   // 返回节点数据的引用
}
  • 普通迭代器:返回 T&,可修改
  • const 迭代器:返回 const T&,只读

4.2 箭头 operator->

cpp 复制代码
Ptr operator->()
{
    return &_node->_data;   // 返回数据指针
}

🐾如果 T 是自定义类型,it->member 等价于 (*it).member


4.3 前置 ++ / 后置 ++

cpp 复制代码
// 前置++:返回移动后的迭代器
Self& operator++()
{
    _node = _node->_next;
    return *this;
}

// 后置++:返回移动前的副本,然后移动
Self operator++(int)
{
    Self tmp(*this);
    _node = _node->_next;
    return tmp;
}

4.4 前置 -- / 后置 --

cpp 复制代码
// 前置--:向前移动
Self& operator--()
{
    _node = _node->_prev;
    return *this;
}

// 后置--:返回移动前的副本
Self operator--(int)
{
    Self tmp(*this);
    _node = _node->_prev;
    return tmp;
}

4.5 比较运算符

cpp 复制代码
bool operator!=(const Self& s) const
{
    return _node != s._node;
}

bool operator==(const Self& s) const
{
    return _node == s._node;
}

🐶 🐾 ✨ 🐾 🐶


5. list 类的主体框架与构造

5.1 类成员变量

cpp 复制代码
template<class T>
class list
{
    using Node = list_node<T>;

private:
    Node* _head;      // 哨兵头节点指针
    size_t _size = 0; // 有效数据节点个数
};

5.2 默认构造

cpp 复制代码
list()
{
    empty_init();     // 创建哨兵位头节点,形成自环
}

5.3 初始化列表构造

cpp 复制代码
list(initializer_list<T> il)
{
    empty_init();
    for (auto& e : il)
    {
        push_back(e);
    }
}

5.4 迭代器区间构造(函数模板)

cpp 复制代码
template <class InputIterator>
list(InputIterator first, InputIterator last)
{
    empty_init();
    while (first != last)
    {
        push_back(*first);
        ++first;
    }
}

使用 InputIterator 而非具体类型,可以接受任意容器的迭代器(vector、array、原生指针等)。


5.5 析构函数

cpp 复制代码
~list()
{
    clear();          // 先删除所有数据节点
    delete _head;     // 再删除哨兵头节点
    _head = nullptr;  // 置空避免野指针
    _size = 0;
}

🐶 🐾 ✨ 🐾 🐶


6. 增删操作:insert、erase 与复用

6.1 insert:任意位置插入(O(1))

cpp 复制代码
void insert(iterator pos, const T& x)
{
    Node* cur = pos._node;      // pos 指向的当前节点
    Node* prev = cur->_prev;    // 当前节点的前驱
    Node* newnode = new Node(x); // 新建节点

    // 调整指针:prev <-> newnode <-> cur
    newnode->_prev = prev;
    newnode->_next = cur;
    prev->_next = newnode;
    cur->_prev = newnode;

    ++_size;
}

6.2 erase:任意位置删除(O(1))

cpp 复制代码
iterator erase(iterator pos)
{
    assert(pos != end());              // 不能删除哨兵位
    Node* prev = pos._node->_prev;
    Node* next = pos._node->_next;

    prev->_next = next;                // 前驱指向后继
    next->_prev = prev;                // 后继指向前驱

    delete pos._node;                  // 释放节点
    --_size;

    return next;                       // 返回被删除节点的下一个位置(避免迭代器失效)
}

6.3 复用:push_back、push_front、pop_back、pop_front

cpp 复制代码
void push_back(const T& x)  { insert(end(), x); }   // 尾插:在哨兵位前插入
void push_front(const T& x) { insert(begin(), x); } // 头插:在第一个节点前插入
void pop_back()             { erase(--end()); }     // 尾删:删除最后一个节点
void pop_front()            { erase(begin()); }     // 头删:删除第一个节点

6.4 clear:清空所有数据节点

cpp 复制代码
void clear()
{
    iterator it = begin();
    while (it != end())
    {
        it = erase(it);   // 逐个删除,it 自动更新
    }
}

注意 :clear 只删除数据节点,保留哨兵位头节点,便于后续复用。

🐶 🐾 ✨ 🐾 🐶


7. 迭代器接口与 const 版本

cpp 复制代码
// 普通迭代器
iterator begin() { return iterator(_head->_next); }
iterator end()   { return iterator(_head); }

// const 迭代器(只读)
const_iterator begin() const { return const_iterator(_head->_next); }
const_iterator end() const   { return const_iterator(_head); }
  • begin() 指向第一个有效数据节点(_head->_next)
  • end() 指向哨兵位头节点(_head),作为遍历结束标志

🐶 🐾 ✨ 🐾 🐶


8. 完整测试用例

test 1 :基础插入与遍历

cpp 复制代码
void test_list1()
{
    QianYv::list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);

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

    for (auto e : lt)         // 范围 for
    {
        cout << e << " ";     // 1 2 3 4
    }
}

test 2 :头插尾插与头删尾删

cpp 复制代码
void test_list2()
{
    QianYv::list<int> lt;
    lt.push_front(-2);
    lt.push_front(-1);
    lt.push_back(1);
    lt.push_back(2);
    // 预期:-1 -2 1 2

    lt.pop_back();    // 删除 2
    lt.pop_back();    // 删除 1
    lt.pop_front();   // 删除 -1
    lt.pop_front();   // 删除 -2

    cout << lt.size();  // 0
}

test 3 :拷贝构造与 const 迭代器

cpp 复制代码
void Print(const QianYv::list<int>& lt)
{
    QianYv::list<int>::const_iterator it = lt.begin();
    while (it != lt.end())
    {
        // *it = 10;  // ❌ 编译报错:const 迭代器不可修改
        cout << *it << " ";
        ++it;
    }
}

void test_list3()
{
    QianYv::list<int> lt1 = { 1, 2, 3, 4, 5, 6 };
    QianYv::list<int> lt2(lt1);        // 拷贝构造
    Print(lt1);                         // 1 2 3 4 5 6
}

test 4 :insert、erase 与 clear

cpp 复制代码
void test_list4()
{
    QianYv::list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    lt.push_back(4);

    // 在第二个位置插入 100
    auto it = lt.begin();
    ++it;
    lt.insert(it, 100);      // 1 100 2 3 4

    // 删除 100
    it = lt.begin();
    ++it;
    it = lt.erase(it);       // 1 2 3 4

    lt.clear();
    cout << lt.size();       // 0
}

🐶 🐾 ✨ 🐾 🐶


9. 总结

核心知识点:

模块 关键实现
节点结构 _prev、_next、_data
哨兵位设计 空链表自环,简化边界条件
迭代器封装 类封装节点指针,重载运算符模拟指针
三模板参数 一套代码同时生成普通/const 迭代器
插入删除 insert/erase 的 O(1) 指针操作
接口复用 push_back 复用 insert(end())

与 vector 的对比

特性 vector list
内存布局 连续数组 分散节点 + 指针链接
迭代器类型 随机迭代器 (支持 +n)
中间插入/删除 O(n) 需移动元素 O(1) 只需改指针
迭代器失效 扩容时全部失效 仅被删除节点失效
适用场景 频繁随机访问 频繁中间插入/删除

🐶 🐾 ✨ 🐾 🐶


本文全部代码

🐾 list.h

cpp 复制代码
#pragma once
#include<iostream>
#include<list>
#include<cassert>
using namespace std;

//模板参数T:支持任意数据类型(替代)----QianYv::list<int>存储整数、QianYv::<string>存储字符串,与string泛型设计一致
//默认构造函数:T()确保内置类型(如int)默认初始化为0,自定义类型自动调用其默认构造函数
//指针初始化:_prev和_next初始化为nullptr,避免野指针风险,后续由容器类统一管理


namespace QianYv			//避免与 std::list冲突
{

	//链表节点结构:存储数据与双向指针
	template<class T>

	//定义链表节点结构体
	struct list_node
	{
		//成员变量
		list_node<T>* _prev;  // 前驱节点指针
		list_node<T>* _next;  // 后继节点指针
		T _data;              // 节点数据,用来存数据(int、string、对象...)

		// 构造函数:默认值初始化,指针置空

		list_node(const T& x = T())
			//T()确保内置类型(如int)默认初始化为0,自定义类型自动调用其默认构造函数

			: _prev(nullptr)
			, _next(nullptr)
			, _data(x)
		{

		}
	};


//迭代器类:T->数据类型,Ref->引用类型(T& 或 const T&),Ptr->指针类型(T* 或 const T*)

	template<class T, class Ref, class Ptr>
	
	//T:接节点储存的数据类型(int...)
	//Ref:数据引用的类型(普通迭代器是T&,const迭代器是const T&)
	//Ptr:数据的指针类型(普通迭代器是T*,cosnt迭代器是const T*)

	//这样设计的原理:为了复用一套代码,同时生成两种迭代器,避免重复写


//1.普通迭代器
	//list_iterator的核心封装结构,把底层节点指针包装成一把智能指针,让用户可以用像指针一样的语法去访问链表

	struct list_iterator
	{
		using Self = list_iterator<T, Ref, Ptr>;  // 简化自身类型名
		using Node = list_node<T>;                // 节点类型别名

		Node* _node;                              // _node本质是封装节点指针,模拟指针行动

		// 迭代器构造:接收节点指针(_node),来初始化迭代器
		list_iterator(Node* node)
			: _node(node)
		{

		}

		// 1.重载解引用operator*:获取节点数据(普通迭代器可修改,const不可)
		//Ref:数据引用的类型(普通迭代器是T&,const迭代器是const T&)
		
		Ref operator*()	
		{
			return _node->_data;
		}

		// 2.重载箭头operator->:支持访问自定义类型(如struct.field)
		
		Ptr operator->()
		{
			return &_node->_data;
		}

		// 3. 重载前置++:实现迭代器向后移动(指向后继节点)
		Self& operator++()
		{
			_node = _node->_next;
			return *this;
		}

		// 4. 重载后置++:先返回当前,再移动
		Self operator++(int)
		{
			Self tmp(*this);
			_node = _node->_next;
			return tmp;
		}

		// 5. 重载前置--:向前移动(指向前驱节点)
		Self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}

		// 6. 重载后置--:先返回当前,再移动
		Self operator--(int)
		{
			Self tmp(*this);
			_node = _node->_prev;
			return tmp;
		}

		// 7. 重载相等判断:比较底层节点指针是否相同,用于遍历结束判断
		bool operator!=(const Self& s) const
		{
			return _node != s._node;
		}

		bool operator==(const Self& s) const
		{
			return _node == s._node;
		}
	};



	



//2.const迭代器
 
	//list的迭代器不是原生指针而是封装list_node*的类,通过运算符重载模拟指针行为,
	//同时"三模版参数"复用普通/const迭代器
	template<class T>

	class list
	{
		using Node = list_node<T>;  // 节点类型别名:Node

		//typedef List_node<T> Node;
	public:

		// 类型重定义:普通/const迭代器(复用list_iterator)
		using iterator = list_iterator<T, T&, T*>;
		using const_iterator = list_iterator<T, const T&, const T*>;

		// typedef list_iterator<T,T&,T*> iterator;
		// typedef list_iterator<T,const T&,const T*>

	// -------------------------- 迭代器接口 --------------------------
		
	//_head:哨兵位头节点
	//begin()返回第一个数据节点的迭代器
		iterator begin()
		{
			return iterator(_head->_next);
		}

		//end()返回哨兵位头节点的迭代器
		iterator end()
		{
			return iterator(_head);
		}

		const_iterator begin() const
		{
			return const_iterator(_head->_next);
		}

		const_iterator end() const
		{
			return const_iterator(_head);
		}

		// -------------------------- 初始化接口 --------------------------

		// 1.空链表初始化:创建哨兵头节点,形成自环
		void empty_init()
		{
			_head = new Node;
			_head->_prev = _head;
			_head->_next = _head;
			_size = 0;
		}

		// 2.默认构造
		//所有构造都先调用empty_init()统一初始化逻辑
		list()
		{
			empty_init();//创建哨兵位头节点,使其前后指针指向自身,指向循环链表
		}

		// 3.初始化列表构造(支持{1,2,3}形式)
		list(initializer_list<T> il)
		{
			empty_init();
			for (auto& e : il)
			{
				push_back(e);
			}
		}

		//4.范围构造函数(支持[first, last)区间)
		//模板参数InputTterator:支持任意输入跌打起(可以是数组指针,其他容器的迭代器等)

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

		//5. 析构函数:释放所有节点,避免内存泄漏
		~list()
		{
			clear();          // 先删除所有数据节点
			delete _head;     // 再删除哨兵头节点
			_head = nullptr;  // 置空指针,避免野指针
			_size = 0;
		}

		// -------------------------- 插入删除接口 --------------------------

		// 尾插:复用insert,简化代码
		void push_back(const T& x) { insert(end(), x); }

		// 头插:复用insert
		void push_front(const T& x) { insert(begin(), x); }

		// 尾删:复用erase
		void pop_back() { erase(--end()); }

		// 头删:复用erase
		void pop_front() { erase(begin()); }

		// 任意位置插入:调整指针实现O(1)插入
		void insert(iterator pos, const T& x)
		{
			Node* cur = pos._node;    // pos指向的当前节点
			Node* prev = cur->_prev;  // 当前节点的前驱
			Node* newnode = new Node(x);  // 新建数据节点

			// 调整指针:prev <-> newnode <-> cur
			newnode->_prev = prev;
			newnode->_next = cur;
			prev->_next = newnode;
			cur->_prev = newnode;

			++_size;  // 有效元素个数递增
		}

		//任意位置删除
		iterator erase(iterator pos)
		{
			assert(pos != end());
			Node* prev = pos._node->_prev;
			Node* next = pos._node->_next;

			prev->_next = next;
			next->_prev = prev;

			delete pos._node;
			--_size;

			return next; // 返回合法的下一个迭代器
		}

		// 清空容器:保留哨兵头节点,便于后续复用
		void clear()
		{
			iterator it = begin();
			while (it != end()) it = erase(it);
		}

		// -------------------------- 其他接口 --------------------------
		// 获取有效元素个数
		size_t size() const { return _size; }

	private:
		Node* _head;   // 哨兵头节点指针
		size_t _size = 0;  // 有效数据节点个数
	};
}

🐾 Test.cpp

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"list.h"
using namespace std;


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

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

	for (auto e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}

//int main()
//{
//	test_list1();
//	return 0;
//}
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void test_list2()
{
	QianYv::list<int> lt;
	// 头插2个元素,尾插2个元素
	lt.push_front(-2);
	lt.push_front(-1);
	lt.push_back(1);
	lt.push_back(2);

	cout << "头插+尾插后:";
	for (auto e : lt)
	{
		cout << e << " ";		// 预期输出:-1 -2 1 2
	}
	cout << endl;

	// 尾删2次,头删2次
	lt.pop_back();
	lt.pop_back();
	lt.pop_front();
	lt.pop_front();

	cout << "删除后size:" << lt.size() << endl;  // 预期输出:0
	cout << endl;
}
//
//int main()
//{
//	test_list2();
//	return 0;
//}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////


// 用const迭代器遍历的打印函数(验证只读特性)
void Print(const  QianYv::list<int>& lt)
{
	QianYv::list<int>::const_iterator it = lt.begin();
	while (it != lt.end())
	{
		// *it = 10;  // 编译报错:const迭代器不可修改数据
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

void test_list3()
{
	// 初始化列表构造
	QianYv::list<int> lt1 = { 1,2,3,4,5,6 };

	// 拷贝构造
	QianYv::list<int> lt2(lt1);
	cout << "lt2(拷贝lt1):";

	for (auto e : lt2)
	{
		cout << e << " ";		// 预期输出:1 2 3 4 5 6
	}
	cout << endl;

	// const迭代器遍历
	const  QianYv::list<int>& clt = lt1;
	cout << "const迭代器遍历lt1:";
	Print(clt);  // 预期输出:1 2 3 4 5 6
	cout << endl;
}

//int main()
//{
//	test_list3();
//	return 0;
//}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////


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

	// 任意位置插入
	auto it = lt.begin();
	++it;				//在第2个元素(2)前插入100
	lt.insert(it, 100);
	cout << "插入100后:";
	for (auto e : lt) cout << e << " ";  // 预期输出:1 100 2 3 4
	cout << endl;


	// 任意位置删除:删除100
	it = lt.begin();
	++it;				//删除第2个元素:100
	it = lt.erase(it);
	cout << "删除100后:";
	for (auto e : lt) cout << e << " ";  // 预期输出:1 2 3 4
	cout << endl;

	// 清空容器
	lt.clear();
	cout << "clear后size:" << lt.size() << endl;  // 预期输出:0
}

int main()
{
	test_list4();
	return 0;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//int main()
//{
//	test_list1();
//	test_list2();
//	test_list3();
//	test_list4();
//	return 0;
//}
  1. 欢迎留言交流
  2. 期待你的评论与建议
  3. 留下你的想法吧

谢谢你看到这里呀

如果喜欢这篇内容,点个关注,下次更新不迷路✨

👍 点赞 ⭐ 收藏 💬 评论

相关推荐
liulilittle2 小时前
过冲:拥塞控制的呼吸与盲行
linux·网络·c++·tcp/ip·计算机网络·tcp·通信
人道领域2 小时前
【LeetCode刷题日记】93.复原IP地址
java·开发语言·算法·leetcode
caimouse2 小时前
Reactos 第 3 章 内存管理 — 【中篇】Hyperspace、系统空间、API 与异常
c语言·开发语言·windows·架构
摇滚侠2 小时前
JavaWeb 全套教程 Listener 112-113
java·开发语言·servlet·tomcat·intellij-idea
ysu_03142 小时前
leetcode数据结构与算法1~4
c语言·数据结构·学习·算法·leetcode
Oll Correct2 小时前
实验三十一:配置DHCP中继代理
网络·笔记
小欣加油2 小时前
leetcode2574 左右元素和的差值
数据结构·c++·算法·leetcode·职场和发展
hixiong1232 小时前
C# Tokenizers.DotNet测试工具
开发语言·人工智能·llm
曹牧2 小时前
Java:Deprecated 是
java·开发语言