体会插入迭代器

本文探讨了C++中使用不同类型的迭代器向列表插入元素的方法,并对比了back_inserter、front_inserter与inserter之间的差异及应用。通过具体代码示例展示了如何使用这些迭代器并解释了inserter的特殊用法。

《《C++Primer》》第五版中文版359页

#include<iostream>
#include<vector>
#include<sstream>
#include<fstream>
#include<cstdlib>
#include<list>
#include<cstring>
#include<string>
#include<deque>
using namespace std;
int main()
{
	list<int>ilis={1,2,3,4};
	list<int> ilis2,ilis3,ilis4;
	copy(ilis.begin(),ilis.end(),back_inserter(ilis2));
	typedef list<int>::iterator QQ;
	QQ it=ilis2.begin();
	while(it!=ilis2.end())
	{
		cout<<*it<<"  ";
		++it;
	}
	cout<<endl;
	copy(ilis.begin(),ilis.end(),front_inserter(ilis3));
	it=ilis3.begin();
	while(it!=ilis3.end())
	{
		cout<<*it<<"  ";
		++it;
	}
	cout<<endl;
	copy(ilis.begin(),ilis.end(),inserter(ilis4,ilis4.begin()));
	it=ilis4.begin();
	while(it!=ilis4.end())
	{
		cout<<*it<<"  ";
		++it;
	}
	return 0;
}

三个插入迭代器,前插和后插相对好理解一些。inserter插入迭代器的特别之处是给出了一个给定的位置,书中貌似没有强调这个位置可以是不存在的???。如本题中给出的空的ilis4.begin().个人理解这样可以的原因是 每次插入的时候都不会重新计算这个迭代器,因为插入的结果顺序没有变

对inserter的理解有点问题。。。。

#include using namespace std; templateclass list { public: // 缺省构造 list() : m_head(NULL), m_tail(NULL) {} // 拷贝构造 list( const list& that ) : m_head(NULL),m_tail(NULL) { for( node* pnode=that.m_head; pnode!=NULL; pnode=pnode->m_next ) { push_back(pnode->m_data); } } // 析构函数 ~list() { clear(); } // 链表判空 bool empty() const { return m_headNULL && m_tailNULL; } // 添加头节点 void push_front( const T& data ) { m_head = new node( NULL, data, m_head ); if( m_head->m_next ) m_head->m_next->m_prev = m_head; else m_tail = m_head; } // 添加尾节点 void push_back( const T& data ) { m_tail = new node( m_tail, data, NULL ); if( m_tail->m_prev ) m_tail->m_prev->m_next = m_tail; else m_head = m_tail; } // 删除头节点 void pop_front() throw(underflow_error) { if( empty() ) throw underflow_error(“null node”); node* pnext = m_head->m_next; delete m_head; if( pnext ) pnext->m_prev = NULL; else m_tail = NULL; m_head = pnext; } // 删除尾节点 void pop_back() { if( empty() ) throw underflow_error(“null node”); node* prev = m_tail->m_prev; delete m_tail; if( prev ) prev->m_next = NULL; else m_head = NULL; m_tail = prev; } // 获取头节点数据 T front() const throw(out_of_range) { if( empty() ) throw out_of_range(“null node”); return m_head->m_data; } // 获取尾节点数据 T back() const throw(out_of_range) { if( empty() ) throw out_of_range(“null node”); return m_tail->m_data; } // 链表清空 void clear() { while( !empty() ) { pop_front(); } } // 获取链表大小 size_t size() const { size_t i = 0; for( node* pnode=m_head; pnode!=NULL; pnode=pnode->m_next ) { i; } return i; } private: // 节点类 class node { public: node( node* prev, const T& data, node* next ) : m_prev(prev),m_data(data),m_next(next) {} node* m_prev; // 前指针 T m_data; node* m_next; // 后指针 }; public: // 非常迭代类(用于非常容器) class iterator { public: iterator( node* start, node* cur, node* end ) : m_start(start),m_cur(cur),m_end(end) {} iterator& operator() { if( m_cur == NULL ) m_cur = m_start; else m_cur = m_cur->m_next; return this; } iterator& operator–() { if( m_curNULL ) m_cur = m_end; else m_cur = m_cur->m_prev; return this; } T& operator() throw(out_of_range) { if( m_curNULL ) throw out_of_range(“null node”); return m_cur->m_data; } bool operator==( const iterator& that ) const { return m_startthat.m_start && m_curthat.m_cur && m_endthat.m_end; } bool operator!=( const iterator& that ) const { return !(*thisthat); } private: node m_start; // 开始指向 node* m_cur; // 当前指向 node* m_end; // 终止指向 friend class list; }; // 常迭代类(用于常容器) class const_iterator { public: const_iterator( node* start, node* cur, node* end ) : m_start(start),m_cur(cur),m_end(end) {} const_iterator& operator++() { if( m_cur == NULL ) m_cur = m_start; else m_cur = m_cur->m_next; return this; } const_iterator& operator–() { if( m_cur == NULL ) m_cur = m_end; else m_cur = m_cur->m_prev; return this; } const T& operator() throw(out_of_range) { // 重点体会为什么在这里加const if( m_curNULL ) throw out_of_range(“null node”); return m_cur->m_data; } bool operator( const const_iterator& that ) const { return m_startthat.m_start && m_curthat.m_cur && m_endthat.m_end; } bool operator!=( const const_iterator& that ) const { return !(*thisthat); } private: node m_start; node* m_cur; node* m_end; }; // 创建非常起始迭代器(用于遍历) iterator begin() { return iterator(m_head,m_head,m_tail); } // 创建非常终止迭代器(结束标识) iterator end() { return iterator(m_head,NULL,m_tail); } // 创建常起始迭代器(用于遍历) const_iterator begin() const { return const_iterator(m_head,m_head,m_tail); } // 创建常终止迭代器(结束标识) const_iterator end() const { return const_iterator(m_head,NULL,m_tail); } // 在迭代器指向的位置添加节点 void insert( const iterator& loc, const T& data ) { if( loc == end() ) { push_back( data ); } else { node* pnew = new node(loc.m_cur->m_prev, data, loc.m_cur ); if( pnew->m_prev ) pnew->m_prev->m_next = pnew; else m_head = pnew; pnew->m_next->m_prev = pnew; } } // 删除迭代器指向的节点 void erase( const iterator& loc ) { if( locend() ) throw out_of_range(“null node”); node* pdel = loc.m_cur; if( pdel->m_prev ) pdel->m_prev->m_next = pdel->m_next; else { pdel->m_next->m_prev = NULL; m_head = pdel->m_next; } if( pdel->m_next ) pdel->m_next->m_prev = pdel->m_prev; else { pdel->m_prev->m_next = NULL; m_tail = pdel->m_prev; } delete pdel; } private: node* m_head; // 链表头指针 node* m_tail; // 链表尾指针 }; // 利用"“比较查找 template<typename IT, typename T> IT find( const IT& beg, const IT& end, const T& data ) { for( IT it=beg; it!=end; ++it ) { if( *it==data ) { return it; } } return end; } // 利用”<"实现的排序 templatevoid sort( const IT& beg, const IT& end ) { IT last = end; –last; IT p = beg; for( IT i=beg, j=last; i!=j; ) { while( i!=p && *i<*p ) { ++i; } if( i!=p ) { swap( *i, *p ); } while( j!=p && *p<*j ) { –j; } if( j!=p ) { swap( *p, *j ); } } IT it = beg; ++it; if( p!=beg && p!=it ) { sort( beg, p ); } it = p; ++it; if( it!=end && it!=last ) { sort( it, end ); } } // 容器设计者提供比较类 templateclass Greater { public: bool operator()( T x, T y) { return x > y; } }; // 利用"比较器"实现的排序 template<typename IT, typename CMP>void sort( const IT& beg, const IT& end, CMP cmp ) { IT last = end; –last; IT p = beg; for( IT i=beg, j=last; i!=j; ) { while( i!=p && cmp(*i,*p) ) { // cmp.operator()(*i,*p) ++i; } if( i!=p ) { swap( *i, *p ); } while( j!=p && cmp(*p,*j) ) { // cmp.operator()(*p,*j) –j; } if( j!=p ) { swap( *p, *j ); } } IT it = beg; ++it; if( p!=beg && p!=it ) { sort( beg, p, cmp ); } it = p; ++it; if( it!=end && it!=last ) { sort( it, end, cmp ); } } // 以上代码容器的设计者 // ----------------------- // 以下代码容器的使用者 void Print( const string& str, const list& l ) { cout << str << endl; typedef list::const_iterator CIT; for( CIT it=l.begin(); it!=l.end(); ++it ) { cout << *it << ’ '; } cout << endl << “----------------------------” << endl; } // 用户设计比较类 class ZJW { public: bool operator()( int x, int y ) { return x < y; } }; int main( void ) { list ls; // 非常容器(非常对象) for( int i=0; i<5; i++ ) { ls.push_front(1000+i); } for( int i=0; i<5; i++ ) { ls.push_back(100+i); } Print( "添加头尾节点后:", ls ); ls.pop_front(); ls.pop_back(); Print( "删除头尾节点后:", ls ); ls.insert( ++ls.begin(), 888 ); // 增 Print( "迭代器指向的位置添加节点后:", ls ); ls.erase( ----ls.end() ); // 删 Print( "删除迭代器指向的节点后:", ls ); typedef list<int>::iterator IT; IT it = ls.begin(); *it = 999; // 改 Print( "修改迭代器指向的节点后:", ls ); IT fit = find( ls.begin(), ls.end(), 100 ); // 查 if( fit != ls.end() ) { ls.erase( fit ); } Print( "找到100并删除后:", ls ); // sort( ls.begin(), ls.end() ); // 利用<排序 // sort( ls.begin(), ls.end(), ZJW() ); // 利用 用户自己设计的比较器 Greater<int> g;// 容器设计者提供的比较器 sort( ls.begin(), ls.end(), g ); // 利用 容器设计者提供的比较器 Print( "排序后:", ls ); const list<int> cls = ls; // 常容器(常对象) Print( "常容器:", cls ); sort( cls.begin(), cls.end(), ZJW() ); Print( "排序后:", cls ); return 0; } 帮我注释这段代码,并且为我解释里面迭代器有关的知识
07-15
<think>我们有一个模板类 list,它实现了一个双向链表。我们将逐步注释代码,并重点解释迭代器部分。 首先,我们定义 list 类模板,它包含节点类 node 和迭代器类 iterator 和 const_iterator。 迭代器的作用是提供一种访问容器元素的方法,而不需要暴露容器的内部结构。迭代器类似于指针,可以用于遍历容器中的元素。 在 list 中,我们定义了两个迭代器类:iterator 和 const_iterator。iterator 用于非常量链表,允许修改元素;const_iterator 用于常量链表,不允许修改元素。 迭代器的实现通常包括以下几个部分: 1. 迭代器的构造函数:用于初始化迭代器指向的位置。 2. 重载运算符:包括自增(++)、自减(--)、解引用(*)、相等(==)和不等(!=)等。 在 list 类中,我们提供了四个成员函数来获取迭代器: - begin(): 返回指向第一个元素的迭代器。 - end(): 返回指向最后一个元素之后的迭代器(作为结束标志)。 - const 版本的 begin() 和 end():用于常量对象。 下面我们逐部分注释代码,并解释迭代器相关的知识。</think>### 代码注释及迭代器解析 ```cpp #include <iostream> #include <stdexcept> #include <string> using namespace std; // 双向链表模板类 template<typename T> class list { public: // 节点类(链表的基本单元) class node { public: node(node* prev, const T& data, node* next) : m_prev(prev), m_data(data), m_next(next) {} node* m_prev; // 指向前驱节点的指针 T m_data; // 节点存储的数据 node* m_next; // 指向后继节点的指针 }; private: node* m_head; // 链表头指针 node* m_tail; // 链表尾指针 public: // 迭代器类(用于非const容器) class iterator { private: node* m_start; // 链表起始位置 node* m_cur; // 当前指向的节点 node* m_end; // 链表结束位置 friend class list; // 允许list访问私有成员 public: // 构造函数 iterator(node* start, node* cur, node* end) : m_start(start), m_cur(cur), m_end(end) {} // 前置++运算符(移动到下一个节点) iterator& operator++() { if (m_cur == NULL) m_cur = m_start; // 若当前为空则重置到起始 else m_cur = m_cur->m_next; // 否则指向下一个节点 return *this; } // 前置--运算符(移动到上一个节点) iterator& operator--() { if (m_cur == NULL) m_cur = m_end; // 若当前为空则重置到末尾 else m_cur = m_cur->m_prev; // 否则指向上一个节点 return *this; } // 解引用运算符(获取当前节点的数据引用) T& operator*() throw(out_of_range) { if (m_cur == NULL) throw out_of_range("null node"); return m_cur->m_data; // 返回数据引用(可修改) } // 相等运算符 bool operator==(const iterator& that) const { return m_cur == that.m_cur; // 只需比较当前节点指针 } // 不等运算符 bool operator!=(const iterator& that) const { return !(*this == that); } }; // const迭代器类(用于const容器) class const_iterator { private: node* m_start; node* m_cur; node* m_end; public: const_iterator(node* start, node* cur, node* end) : m_start(start), m_cur(cur), m_end(end) {} const_iterator& operator++() { /* 同iterator */ } const_iterator& operator--() { /* 同iterator */ } // 返回const引用(禁止修改数据) const T& operator*() throw(out_of_range) { if (m_cur == NULL) throw out_of_range("null node"); return m_cur->m_data; // 返回常量引用(不可修改) } bool operator==(const const_iterator& that) const { /* 同iterator */ } bool operator!=(const const_iterator& that) const { /* 同iterator */ } }; // 获取起始迭代器(非const版) iterator begin() { return iterator(m_head, m_head, m_tail); } // 获取结束迭代器(非const版) iterator end() { return iterator(m_head, NULL, m_tail); // 当前指针为NULL表示结束 } // 获取起始迭代器(const版) const_iterator begin() const { return const_iterator(m_head, m_head, m_tail); } // 获取结束迭代器(const版) const_iterator end() const { return const_iterator(m_head, NULL, m_tail); } // 在迭代器位置插入新节点 void insert(const iterator& loc, const T& data) { if (loc == end()) { push_back(data); // 在末尾插入 } else { // 创建新节点(前驱=loc节点的前驱,后继=loc节点) node* pnew = new node(loc.m_cur->m_prev, data, loc.m_cur); // 调整前驱节点的后继指针 if (pnew->m_prev) pnew->m_prev->m_next = pnew; else m_head = pnew; // 新节点成为头节点 // 调整后继节点的前驱指针 pnew->m_next->m_prev = pnew; } } // 删除迭代器指向的节点 void erase(const iterator& loc) { if (loc == end()) throw out_of_range("null node"); node* pdel = loc.m_cur; // 待删除节点 // 调整前驱节点的后继指针 if (pdel->m_prev) pdel->m_prev->m_next = pdel->m_next; else { m_head = pdel->m_next; // 删除头节点 if (m_head) m_head->m_prev = NULL; } // 调整后继节点的前驱指针 if (pdel->m_next) pdel->m_next->m_prev = pdel->m_prev; else { m_tail = pdel->m_prev; // 删除尾节点 if (m_tail) m_tail->m_next = NULL; } delete pdel; } // 其他链表操作(push_front/pop_back等)已省略... }; // 查找算法(使用迭代器遍历) template<typename IT, typename T> IT find(const IT& beg, const IT& end, const T& data) { for (IT it = beg; it != end; ++it) { if (*it == data) return it; // 解引用比较数据 } return end; // 未找到 } ``` --- ### 迭代器核心知识解析 1. **迭代器的本质** - 是容器和算法之间的桥梁,提供统一的访问接口 - 行为类似指针(支持`++`、`--`、`*`等操作) - 示例:`list<int>::iterator it = ls.begin();` 2. **const迭代器 vs 普通迭代器** ```cpp const list<int> cls; // 常量容器 list<int>::const_iterator cit = cls.begin(); // 必须使用const迭代器 *cit = 10; // 错误!const迭代器禁止修改数据 list<int> ls; // 非常量容器 list<int>::iterator it = ls.begin(); *it = 20; // 允许修改 ``` 3. **迭代器失效场景** - 删除当前元素会导致迭代器失效: ```cpp auto it = ls.begin(); ls.erase(it); // 删除后it失效 ++it; // 危险!未定义行为 ``` - 正确做法:获取erase返回的新迭代器(此实现未返回,需谨慎) 4. **迭代器与算法结合** ```cpp // 标准算法模式 template<typename InputIt, typename T> InputIt find(InputIt first, InputIt last, const T& value) { while (first != last) { if (*first == value) return first; ++first; } return last; } ``` 5. **迭代器分类** | 类 | 支持操作 | 典容器 | |------|----------|----------| | 输入迭代器 | `++`, `*`, `==` | `istream` | | 前向迭代器 | 输入迭代器+多趟遍历 | `forward_list` | | 双向迭代器 | 前向迭代器+`--` | `list`, `map` | | 随机访问 | 双向+`+n`, `-n`, `[]` | `vector`, `deque` | --- ### 关键问题修复 原代码中迭代器比较运算符实现有误: ```cpp // 错误实现(多余比较m_start/m_end) bool operator==(const iterator& that) const { return m_start == that.m_start && m_cur == that.m_cur && m_end == that.m_end; } // 正确实现(只需比较当前节点) bool operator==(const iterator& that) const { return m_cur == that.m_cur; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值