C++ std::list 执行 erase()还需要手动去delete 节点指向的内存吗

本文探讨了C++STL库中list容器的使用,特别是erase()函数的行为。当调用erase()删除list中的元素时,内部已经处理了节点的释放,因此不需要手动调用delete。通过深入分析erase()函数的源码,确认了这一事实,消除了关于内存管理的疑虑。
摘要由CSDN通过智能技术生成

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

@[TOC](C++ std::list 执行 erase()还需要手动去delete 节点指向的内存吗)


前言

提示:这里可以添加本文要记录的大概内容:

最近在项目中使用C++ STL 库中的 list 容器,所以能好奇 std::list 执行 erase()还需不需要手动去delete 节点指向的内存


提示:以下是本篇文章正文内容,下面案例可供参考

一、C++ STL 库?

示例:C++ STL(标准模板库)是一套功能强大的 C++ 模板类,提供了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量、链表、队列、栈。

C++ 标准模板库的核心包括以下三个组件:

1. 容器(Containers)

容器是用来管理某一类对象的集合。C++ 提供了各种不同类型的容器,比如 deque、list、vector、map 等。

2. 算法(Algorithms)

算法作用于容器。它们提供了执行各种操作的方式,包括对容器内容执行初始化、排序、搜索和转换等操作。

3. 迭代器(iterators)

迭代器用于遍历对象集合的元素。这些集合可能是容器,也可能是容器的子集。

二、list使用步骤

1.示例

代码如下(示例):

#include <algorithm>
#include <iostream>
#include <list>
 
int main()
{
    // 创建含整数的 list
    std::list<int> l = { 7, 5, 16, 8 };
 
    // 添加整数到 list 开头
    l.push_front(25);
    // 添加整数到 list 结尾
    l.push_back(13);
 
    // 以搜索插入 16 前的值
    auto it = std::find(l.begin(), l.end(), 16);
    if (it != l.end()) {
        l.insert(it, 42);
    }
 
    // 迭代并打印 list 的值
    for (int n : l) {
        std::cout << n << '\n';
    }
}

2.疑问

我们来看看 C++ stl list在执行erase()函数的时候内部发生了什么
代码如下(示例):

iterator erase(const_iterator _Where)
		{	// erase element at _Where
 #if _ITERATOR_DEBUG_LEVEL == 2
		if (_Where._Getcont() != this || _Where._Ptr == this->_Myhead)
			_DEBUG_ERROR("list erase iterator outside range");
		_Nodeptr _Pnode = (_Where++)._Mynode();
		_Orphan_ptr(*this, _Pnode);

 #else /* _ITERATOR_DEBUG_LEVEL == 2 */
		_Nodeptr _Pnode = (_Where++)._Mynode();
 #endif /* _ITERATOR_DEBUG_LEVEL == 2 */

		if (_Pnode != this->_Myhead)
			{	// not list head, safe to erase
			this->_Nextnode(this->_Prevnode(_Pnode)) =
				this->_Nextnode(_Pnode);
			this->_Prevnode(this->_Nextnode(_Pnode)) =
				this->_Prevnode(_Pnode);

			_Dest_val(this->_Alnod, _Pnode);
			this->_Alnod.deallocate(_Pnode, 1);

			--this->_Mysize;
			}
		return (_Make_iter(_Where));
		}

在这里插入图片描述
如下图最后 在erase()函数内部有调用delete。
在这里插入图片描述


总结

所以执行 erase()不需要手动去delete节点指向的内存

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于模板的双向循环链表C++实现代码,其中包含注释和支持图形化打印的功能: ```c++ #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<queue> #include<vector> #include<map> #include<set> #include<sstream> #include<iomanip> using namespace std; // 双向循环链表节点定义 template<typename T> struct DListNode{ T data; // 存储数据 DListNode<T>* prev; // 指向前驱节点的指针 DListNode<T>* next; // 指向后继节点的指针 DListNode(T _data = T(), DListNode<T>* _prev = NULL, DListNode<T>* _next = NULL):data(_data), prev(_prev), next(_next){} }; // 双向循环链表的实现 template<typename T> class DList{ public: DList(); // 构造函数 ~DList(); // 析构函数 bool empty() const; // 判断链表是否为空 int size() const; // 获取链表长度 DListNode<T>* front() const; // 获取头节点 DListNode<T>* back() const; // 获取尾节点 void insert(DListNode<T>* pos, const T& val); // 在指定位置插入节点 void erase(DListNode<T>* pos); // 删除指定位置的节点 void push_front(const T& val); // 在头部插入节点 void pop_front(); // 删除头部节点 void push_back(const T& val); // 在尾部插入节点 void pop_back(); // 删除尾部节点 void clear(); // 清空链表 void print() const; // 打印链表 private: int len; // 链表长度 DListNode<T>* head; // 指向节点的指针 DListNode<T>* tail; // 指向节点的指针 }; // 构造函数 template<typename T> DList<T>::DList(){ head = new DListNode<T>(); tail = new DListNode<T>(); head->prev = tail->next = NULL; head->next = tail; tail->prev = head; len = 0; } // 析构函数 template<typename T> DList<T>::~DList(){ clear(); delete head; delete tail; } // 判断链表是否为空 template<typename T> bool DList<T>::empty() const{ return len == 0; } // 获取链表长度 template<typename T> int DList<T>::size() const{ return len; } // 获取头节点 template<typename T> DListNode<T>* DList<T>::front() const{ return empty() ? NULL : head->next; } // 获取尾节点 template<typename T> DListNode<T>* DList<T>::back() const{ return empty() ? NULL : tail->prev; } // 在指定位置插入节点 template<typename T> void DList<T>::insert(DListNode<T>* pos, const T& val){ DListNode<T>* node = new DListNode<T>(val, pos->prev, pos); pos->prev->next = node; pos->prev = node; len++; } // 删除指定位置的节点 template<typename T> void DList<T>::erase(DListNode<T>* pos){ pos->prev->next = pos->next; pos->next->prev = pos->prev; delete pos; len--; } // 在头部插入节点 template<typename T> void DList<T>::push_front(const T& val){ insert(head->next, val); } // 删除头部节点 template<typename T> void DList<T>::pop_front(){ erase(head->next); } // 在尾部插入节点 template<typename T> void DList<T>::push_back(const T& val){ insert(tail, val); } // 删除尾部节点 template<typename T> void DList<T>::pop_back(){ erase(tail->prev); } // 清空链表 template<typename T> void DList<T>::clear(){ while(!empty()){ erase(head->next); } } // 打印链表 template<typename T> void DList<T>::print() const{ DListNode<T>* node = head->next; while(node != tail){ cout<<node->data<<" "; node = node->next; } cout<<endl; } ``` 以下是基于模板的双向循环链表的测试代码,其中包含了图形化打印的功能: ```c++ #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<queue> #include<vector> #include<map> #include<set> #include<sstream> #include<iomanip> #include<windows.h> using namespace std; // 双向循环链表节点定义 template<typename T> struct DListNode{ T data; // 存储数据 DListNode<T>* prev; // 指向前驱节点的指针 DListNode<T>* next; // 指向后继节点的指针 DListNode(T _data = T(), DListNode<T>* _prev = NULL, DListNode<T>* _next = NULL):data(_data), prev(_prev), next(_next){} }; // 双向循环链表的实现 template<typename T> class DList{ public: DList(); // 构造函数 ~DList(); // 析构函数 bool empty() const; // 判断链表是否为空 int size() const; // 获取链表长度 DListNode<T>* front() const; // 获取头节点 DListNode<T>* back() const; // 获取尾节点 void insert(DListNode<T>* pos, const T& val); // 在指定位置插入节点 void erase(DListNode<T>* pos); // 删除指定位置的节点 void push_front(const T& val); // 在头部插入节点 void pop_front(); // 删除头部节点 void push_back(const T& val); // 在尾部插入节点 void pop_back(); // 删除尾部节点 void clear(); // 清空链表 void print() const; // 打印链表 void graphicalPrint() const; // 图形化打印链表 private: int len; // 链表长度 DListNode<T>* head; // 指向节点的指针 DListNode<T>* tail; // 指向节点的指针 }; // 构造函数 template<typename T> DList<T>::DList(){ head = new DListNode<T>(); tail = new DListNode<T>(); head->prev = tail->next = NULL; head->next = tail; tail->prev = head; len = 0; } // 析构函数 template<typename T> DList<T>::~DList(){ clear(); delete head; delete tail; } // 判断链表是否为空 template<typename T> bool DList<T>::empty() const{ return len == 0; } // 获取链表长度 template<typename T> int DList<T>::size() const{ return len; } // 获取头节点 template<typename T> DListNode<T>* DList<T>::front() const{ return empty() ? NULL : head->next; } // 获取尾节点 template<typename T> DListNode<T>* DList<T>::back() const{ return empty() ? NULL : tail->prev; } // 在指定位置插入节点 template<typename T> void DList<T>::insert(DListNode<T>* pos, const T& val){ DListNode<T>* node = new DListNode<T>(val, pos->prev, pos); pos->prev->next = node; pos->prev = node; len++; } // 删除指定位置的节点 template<typename T> void DList<T>::erase(DListNode<T>* pos){ pos->prev->next = pos->next; pos->next->prev = pos->prev; delete pos; len--; } // 在头部插入节点 template<typename T> void DList<T>::push_front(const T& val){ insert(head->next, val); } // 删除头部节点 template<typename T> void DList<T>::pop_front(){ erase(head->next); } // 在尾部插入节点 template<typename T> void DList<T>::push_back(const T& val){ insert(tail, val); } // 删除尾部节点 template<typename T> void DList<T>::pop_back(){ erase(tail->prev); } // 清空链表 template<typename T> void DList<T>::clear(){ while(!empty()){ erase(head->next); } } // 打印链表 template<typename T> void DList<T>::print() const{ DListNode<T>* node = head->next; while(node != tail){ cout<<node->data<<" "; node = node->next; } cout<<endl; } // 图形化打印链表 template<typename T> void DList<T>::graphicalPrint() const{ HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); DListNode<T>* node = head->next; int pos = 0; while(node != tail){ stringstream ss; ss<<node->data; string str; ss>>str; if(pos % 2 == 0){ SetConsoleTextAttribute(hConsole, FOREGROUND_INTENSITY | FOREGROUND_RED); } else{ SetConsoleTextAttribute(hConsole, FOREGROUND_INTENSITY | FOREGROUND_GREEN); } cout<<str<<" -> "; pos++; node = node->next; } SetConsoleTextAttribute(hConsole, FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE); cout<<"NULL\n"; } ``` 测试代码: ```c++ int main(){ DList<int> list; for(int i = 1; i <= 10; i++){ list.push_back(i); } cout<<"The original list is: "; list.print(); cout<<"The graphical print of the original list is:"<<endl; list.graphicalPrint(); DListNode<int>* pos = list.front()->next->next; list.insert(pos, 100); cout<<"After inserting 100 at the third position, the list is: "; list.print(); cout<<"The graphical print of the list after inserting 100 at the third position is:"<<endl; list.graphicalPrint(); pos = list.front()->next; list.erase(pos); cout<<"After erasing the second element, the list is: "; list.print(); cout<<"The graphical print of the list after erasing the second element is:"<<endl; list.graphicalPrint(); list.clear(); cout<<"After clearing the list, the size of the list is "<<list.size()<<endl; cout<<"The graphical print of the list after clearing is:"<<endl; list.graphicalPrint(); return 0; } ``` 输出结果: ``` The original list is: 1 2 3 4 5 6 7 8 9 10 The graphical print of the original list is: 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> NULL After inserting 100 at the third position, the list is: 1 2 100 3 4 5 6 7 8 9 10 The graphical print of the list after inserting 100 at the third position is: 1 -> 2 -> 100 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> NULL After erasing the second element, the list is: 1 100 3 4 5 6 7 8 9 10 The graphical print of the list after erasing the second element is: 1 -> 100 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -> NULL After clearing the list, the size of the list is 0 The graphical print of the list after clearing is: NULL ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值