我可以在迭代它时删除std :: string对象中的元素吗?
for (auto itr = str.rbegin(), rend = str.rend(); itr != str.rend() && *itr == '0'; ++itr)
{
str.pop_back();
}
答案 0 :(得分:4)
不,那是不允许的。修改字符串的内容会使任何迭代器无效,尤其是itr
。
要从字符串中删除尾随字符,请考虑使用find_last_not_of
:
auto ix = str.find_last_not_of('0');
str.resize(ix + 1);
另一种选择是使用erase
函数,该函数将返回序列中的下一个迭代器,从而避免使用任何无效的迭代器。
for (auto itr = str.rbegin(); itr != str.rend() && *itr == '0'; /*nothing*/)
itr = str.erase(itr);
这将删除最后一个字符(如pop_back
所示)并安全地推进迭代器,因此您实际上永远不会有无效的迭代器。需要注意的是,你不能使用之前计算过的rend
迭代器,因为它无效;但是,无论如何你还没有真正使用它。
答案 1 :(得分:2)
根据string::pop_back
http://www.cplusplus.com/reference/string/string/pop_back/
与此对象相关的任何迭代器,指针和引用都可能是 无效。
所以我猜你不能在带有迭代器的for循环中做到这一点。
你这样做:
while ( str.size() > 0 && str[ str.size()-1] == '0' ] )
str.pop_back();
或者您可以使用计数器而不是迭代器来执行for循环。
答案 2 :(得分:2)
你可以在遍历字符串时删除元素,但是你需要稍微改写一下你的循环才能安全地进行。在这种情况下,我们只关心字符串中的最后一个字符,所以我们可以这样做:
for (auto itr = str.rbegin();
itr != str.rend() && *itr == '0';
itr=str.rbegin())
{
str.pop_back();
}
即使我们对字符串执行itr
时pop_back
可能无效,我们也会在每次迭代时重新获取str.rbegin()
的值,并且保证提供有效的反向每当我们调用它时都会使用迭代器。我们留下的内容不再真正好好利用for
循环 - 我们可能也会使用while
循环:
while (str.rbegin() != str.rend() && *str.rbegin() == '0')
str.pop_back();
我想我宁愿写下这样的话:
while (!str.empty() && *str.rbegin() == '0')
str.pop_back();
...或(使用略微更清晰的等同于*str.rbegin()
:
while (!str.empty() && str.back() == '0')
str.pop_back();
答案 3 :(得分:1)
根据圣经,第21.4.1章,第6节:
6引用a的元素的引用,指针和迭代器 basic_string序列可能会被以下用途无效 basic_string对象:
- 作为任何标准库函数的参数 将非const basic_string作为参数引用。
- 调用非const成员函数,除了operator [],at,front,back,begin, rbegin,end和rend。
所以我会说“不,不使用pop_back”。
但是你当然可以使用返回迭代器的erase
重载并使用该迭代器而不是你擦除的迭代器,就像其他容器一样。
答案 4 :(得分:0)
根据标准,s.erase()
上std::basic_string
的任何使用都会使s
的所有指针,引用和迭代器无效。标准中的相关部分是21.4.1 [string.require]第6段:
引用
basic_string
序列元素的引用,指针和迭代器可能会被basic_string
对象的以下用法无效:
- 作为anys标准库函数的参数,引用非
const
basic_string
作为参数。- 调用非
const
成员函数,operator[]
,at
,front
,back
,begin
,rbegin
除外,end
和rend
。
替代方法是使用结果或erase()
将有效迭代器返回到当前位置。或者,您可能希望将erase()
与std::remove_if()
结合使用,首先有效地重新调整字符串,然后删除实际内容。