C++ 在字符串中使用擦除函数会使迭代器无效吗
我有下面的代码,它接受一个字符串并删除非字母字符C++ 在字符串中使用擦除函数会使迭代器无效吗,c++,string,iterator,erase,invalidation,C++,String,Iterator,Erase,Invalidation,我有下面的代码,它接受一个字符串并删除非字母字符 void removeNonAlpha(string& str){ for (string::iterator it = str.begin(); it < str.end(); it++){ if (!(isUpperCaseLetter(*it) || isLowerCaseLetter(*it) || str == ' ')) str.erase(it--); }
void removeNonAlpha(string& str){
for (string::iterator it = str.begin(); it < str.end(); it++){
if (!(isUpperCaseLetter(*it) || isLowerCaseLetter(*it) || str == ' '))
str.erase(it--);
}
}
void removeNonAlpha(字符串和字符串){
对于(string::iterator it=str.begin();it
我向我的教授展示了这一点,他告诉我这样做是有风险的,因为这可能会使我使用的迭代器无效。然而,我认为擦除只会在擦除点之后使迭代器无效,并且我确保在该点之后不使用任何迭代器。
那么,这段代码会崩溃或导致任何未定义的行为吗?
std::vector::erase
按照您的建议工作;它只会使从第一个已擦除元素开始的迭代器无效。但是,这不适用于std::string
C++允许字符串迭代器在帽子的作用下失效。
<> P>传统上,C++标准对<>代码STD::String < /代码>的要求更为灵活。(或者,换句话说,它传统上允许实现者使用对向量无效的优化。)而std::string::erase
和其他字符串变体也是如此
在[string.require]
(n3797的§21.4.1)中,本标准接受:
basic_字符串
序列元素的引用、指针和迭代器可能会因以下使用该basic_字符串
对象而无效:
- 作为任何标准库函数的参数,将对非常量
basic\u字符串的引用作为参数
- 调用非常量成员函数,除了
,操作符[]
,在
,前面
,后面
,开始
,rbegin
,和结束
趋势
std::string::erase
,可能会使该字符串的所有迭代器无效,即使没有对该字符串进行可见的修改(例如,因为要擦除的范围为空)
(最新的C++标准草案有相同的措辞,虽然现在是第4段)。 如果字符串的第一个字符不是字母,则建议的代码涉及未定义的行为。 在字符串的第一个循环中,迭代器
it
的值为str.begin()
。该迭代器不能递减,因为结果不在字符串内。因此,递增递减迭代器可能不会在下一次迭代中将it
返回到str.begin()
使用索引而不是迭代器
以上所有内容均不适用于整数位置索引。因此,如果您可以安全地使用非常类似的
void removeNonAlpha(string& str){
for (auto sz = str.size(), i = 0; i < sz; ++i){
if (!(isUpperCaseLetter(str[i]) ||
isLowerCaseLetter(str[i]) ||
str[i] == ' '))
str.erase(i--);
}
}
void removeNonAlpha(字符串和字符串){
对于(auto sz=str.size(),i=0;i
您可以使用str.erase()的返回值,使用当前占用上一个迭代器所在位置的字符的迭代器更新迭代器。我假设这是一个有效的迭代器,不需要索引。itr=--str.erase(itr)@错误:原则上正确,但如果删除字符串中的唯一字符,则无效(因为在这种情况下不能减少结束迭代器)。另外,后减量的赋值是拙劣的imho。然后您可以执行itr=str.erase(itr);如果(itr!=str.end())--itr;(或从for循环中删除itr++并仅在else上递增)。