C++出现错误:iterator not incrementable

在尝试从C++的set容器中删除偶数元素时遇到'iterator not incrementable'错误。问题出在使用erase()后未正确处理迭代器。解决方法是将迭代器更新为erase()返回的新迭代器。

想要实现一个函数,其功能:删除输入的set容器中的偶数

void select_test(std::set<int>& data)
{
	set<int>::iterator iter;

	for (iter = data.begin(); iter != data.end(); iter++)
	{
		cout << *iter << endl;
	}

	for (iter = data.begin();  iter != data.end(); iter++)
	{
		if (*iter % 2 == 0)
			 vp_data.erase(iter);
	}

	for (iter = vp_data.begin(); iter != vp_data.end(); iter++)
	{
		cout << *iter << endl;
	}
}

发生错误:iterator not incrementable
原因:使用迭代器遍历的时候使用erase()之后会使迭代器失效,但是在迭代器失效的同时这个erase函数会返回一个指向下一个对象的迭代器,所以可以使迭代器重新赋值为erase()的返回值。

void select_test(std::set<int>& data)
{
	set<int>::iterator iter;

	for (iter = data.begin();  iter != data.end(); iter++)
	{
		cout << *iter << endl;
	}

	for (iter = data.begin();  iter != data.end();)
	{
		if (*iter % 2 == 0)
			iter = vp_data.erase(iter);
		else
			iter++;
	}

	for (iter = data.begin();  iter != data.end();  iter++)
	{
		cout << *iter << endl;
	}
}

int main()
{
	int a[] = {11,12,13,14,15,16};
	std::set<int> vp(a,a+6);
	remove_test(vp);
    return 0;
}
### `std::iterator_traits`的用途和功能 `std::iterator_traits`是一个模板类,用于统一提取迭代器类型的各种关联属性。它为编写通用算法提供了必要的支持,使得标准库中的算法能够与各种不同类型的迭代器兼容[^1]。通过这个工具,可以访问迭代器所指向元素的类型、两个迭代器之间的差值类型、指针类型、引用类型以及迭代器的类别。 #### 主要用途 - **获取迭代器的基本属性**:如`value_type`(迭代器指向的元素类型)、`difference_type`(两个迭代器之间的差值类型)、`pointer`(指向迭代器所指向元素的指针类型)、`reference`(对迭代器所指向元素的引用类型)等。 - **判断迭代器类别**:通过`iterator_category`可以获得迭代器的类别,例如输入迭代器、输出迭代器、前向迭代器、双向迭代器或随机访问迭代器。 - **支持泛型编程**:在编写泛型算法时,使用`iterator_traits`可以确保算法能够适应不同的迭代器类型,从而实现更广泛的复用性[^2]。 #### 示例代码 以下是一个简单的示例,展示如何使用`std::iterator_traits`来获取一个迭代器的相关信息: ```cpp #include <iostream> #include <vector> #include <iterator> #include <typeinfo> template<typename Iterator> void print_iterator_info(Iterator it) { typedef typename std::iterator_traits<Iterator>::value_type value_type; typedef typename std::iterator_traits<Iterator>::difference_type difference_type; typedef typename std::iterator_traits<Iterator>::pointer pointer; typedef typename std::iterator_traits<Iterator>::reference reference; typedef typename std::iterator_traits<Iterator>::iterator_category iterator_category; std::cout << "Value type: " << typeid(value_type).name() << '\n'; std::cout << "Difference type: " << typeid(difference_type).name() << '\n'; std::cout << "Pointer type: " << typeid(pointer).name() << '\n'; std::cout << "Reference type: " << typeid(reference).name() << '\n'; std::cout << "Iterator category: " << typeid(iterator_category).name() << '\n'; } int main() { std::vector<int> vec = {1, 2, 3}; auto it = vec.begin(); print_iterator_info(it); return 0; } ``` 在这个示例中,函数`print_iterator_info`接受一个迭代器作为参数,并利用`std::iterator_traits`来获取并打印该迭代器的各种类型信息。这有助于理解不同迭代器的行为,并且可以在编写泛型代码时提供必要的类型支持。 #### 自定义迭代器的支持 当实现自定义迭代器时,必须提供五个基本的类型定义:`value_type`、`difference_type`、`pointer`、`reference`和`iterator_category`。如果自定义迭代器没有直接在其内部定义这些类型,可以通过显式特化`std::iterator_traits`来补充这些信息。例如: ```cpp struct my_iterator { // 假设这里没有定义任何类型别名 }; namespace std { template<> struct iterator_traits<my_iterator> { typedef int value_type; typedef ptrdiff_t difference_type; typedef int* pointer; typedef int& reference; typedef std::random_access_iterator_tag iterator_category; }; } ``` 通过这种方式,即使`my_iterator`本身没有提供那些类型别名,也可以让标准库和其他使用`iterator_traits`的代码能够识别并正确处理这种迭代器。 #### 标准库算法的应用 `std::iterator_traits`不仅限于获取类型信息,它还广泛应用于标准库算法中。例如,在`std::advance`函数中,会根据迭代器的类别调用不同的实现版本: ```cpp template<typename InputIterator, typename Distance> inline void __advance(InputIterator& i, Distance n, std::input_iterator_tag) { while(n--) ++i; } template<typename InputIterator, typename Distance> void advance(InputIterator& i, Distance n) { __advance(i, n, std::iterator_traits<InputIterator>::iterator_category()); } ``` 这段代码展示了如何根据迭代器类别选择适当的实现方式,从而优化性能[^3]。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值