我可以在迭代它时删除std :: string对象中的元素

时间:2013-12-19 15:20:29

标签: c++

我可以在迭代它时删除std :: string对象中的元素吗?

for (auto itr = str.rbegin(), rend = str.rend(); itr != str.rend() && *itr == '0'; ++itr)
{
    str.pop_back();
}

5 个答案:

答案 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();
}

即使我们对字符串执行itrpop_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[]atfrontbackbeginrbegin除外,endrend
  •   

替代方法是使用结果或erase()将有效迭代器返回到当前位置。或者,您可能希望将erase()std::remove_if()结合使用,首先有效地重新调整字符串,然后删除实际内容。