1

我只是想使用 C++11 的基于范围的 for 循环从字符串中删除所有空格;但是,我继续std::out_of_range前进basic_string::erase

#include <iostream>
#include <string>
#include <typeinfo>

int main(){

  std::string str{"hello my name is sam"};

  //compiles, but throws an out_of_range exception
  for(auto i : str){
    std::cout << typeid(i).name();  //gcc outputs 'c' for 'char'
    if(isspace(i)){
      str.erase(i);
    }
  }
  std::cout << std::endl;

  //does not compile - "invalid type argument of unary '*' (have 'char')"
  for(auto i : str){
    if(isspace(*i)){
      str.erase(i);
    }
  }

  //works exactly as expected
  for(std::string::iterator i = begin(str); i != end(str); ++i){
    std::cout << typeid(*i).name();  //gcc outputs 'c' for 'char'
    if(isspace(*i)){
      str.erase(i);
    }
  }
  std::cout << std::endl;

}

所以我想知道:i前两个循环到底是什么?为什么它看起来既是 a char(由 验证typeid)又是iteratora to a char(与 一起使用std::string::erase)?为什么它不等同iterator于最后一个循环?在我看来,它们的功能应该完全相同。

4

1 回答 1

3

i基于范围的for循环中的类型是char,因为字符串的元素是字符(更正式地说,std::string::value_type是 的别名char)。

当您将它传递给它时,它似乎作为迭代器工作的原因erase()是存在的重载erase()接受索引和计数,但后者有一个默认参数:

basic_string& erase( size_type index = 0, size_type count = npos );

并且在您的实现上char恰好可以隐式转换为std::string::size_type. 但是,这可能不会达到您的预期。

要验证它i确实不是迭代器,请尝试取消引用它,您将看到编译器尖叫:

*i; // This will cause an error
于 2013-06-10T10:33:53.283 回答