c ++迭代器循环与索引循环

Posted

技术标签:

【中文标题】c ++迭代器循环与索引循环【英文标题】:c++ iterator loop vs index loop 【发布时间】:2012-05-08 22:21:48 【问题描述】:

我知道这是一个非常愚蠢的问题,但我想澄清一下。

假设我有一个字符串向量看起来像,

vector<int> vnTemp; // suppose this vector has 1,2,3,4,5
vector<int>::iterator vn_it;

//Now, I want to print out only 1 to 4.
for(int i=0; i<4; ++i)
    cout << vnTemp[i] << endl;

很简单。但是当我想使用迭代器打印出等效结果时该怎么办?例如,

// .. continuing from the code above
for(vn_it = vnTemp.begin(); vn_it != vnTemp.end()-1; ++vn_it)
    cout << *it << endl;

当然,vnTemp.end()-1 是指针会导致错误。

在这种情况下,等效的 for 循环是什么? 当它们都在优化(-o)模式下编译时是否有任何性能差异?


编辑:

我刚刚意识到这实际上适用于vector。 问题发生在我使用boost::tokenizer 时 代码是这样的:

typedef boost::tokenizer<boost::char_separator<char> > tokenizer;

boost::char_separator<char> sep("_");
tokenizer::iterator tok_it;

tokenizer tokens(strLine, sep); //strLine is some string line
for(tok_it=tokens.begin(); tok_it != tokens.end(); ++tok_it)
... 

这是原始代码,当我尝试在 for 循环中说 tokens.end()-1 时出现错误。

有什么办法可以解决这个问题吗? 很抱歉有歧义。

【问题讨论】:

应该可以。迭代器实现operator-。此外,迭代器不仅仅是指针。例如,std::list 将其元素保存在非连续内存中。 我会说你的问题有点做作。现实世界的问题通常涉及整个容器,或者以其他方式可以用迭代器很好地编写的选择(如remove_iffind),迭代器确实更合适谈论集合而不是索引的方式。 前向迭代器支持递增,双向迭代器支持递增和递减,随机访问迭代器支持两者以及像begin()+4这样的附加算术...向量使用随机访问迭代器,所以你有选择。我相信boost::tokenizer 默认为std::string::const_iterator boost::token_iterator 是一个 forward_iterator,这就是你有问题的原因。 哦,我明白了。在这种情况下是否可以设置迭代步长? 【参考方案1】:

boost::tokenizer 只提供前向迭代器;这意味着您不能从分词器迭代器中减去。如果您希望循环避免处理最后一个令牌,则必须在处理您所在的令牌之前“先行”。像这样的

tokenizer tokens(strLine, sep); //strLine is some string line
tok_it = tokens.begin();
if(tok_it!=tokens.end())

    ++tok_it;
    for(auto last_tok = tokens.begin(); tok_it != tokens.end(); ++tok_it)
        // Process last_tok here
        . . .
       last_tok = tok_it;    
    

编辑: 另一种方法是将令牌复制到具有更灵活迭代器的容器中:

std::vector<std::string> resultingTokens(tokens.begin(), tokens.end());
for(auto tok=resultingTokens.begin(); tok!=resultingTokens.end()-1; ++tok)

    // whatever

【讨论】:

这个答案基本上是正确的,但它需要一些清理:+1 仍然无法在前向迭代器上工作 - 你只能使用增量运算符:++。此外,更正确的说法是 充其量 boost::tokenizer 会产生前向迭代器。例如,如果底层容器是一个流,boost::tokenizer 将生成稍微受限的输入迭代器。 哎呀。你是对的。谢谢@Michael 如果我想设置步长怎么办?说2?我可以写++(++tok_it)吗? @devEvan:如果你想了解你能做什么和不能做什么(以及为什么),你可能应该尝试一个工作示例。 ++(++tok_it) 应该可以工作,但它会使代码变得复杂。而且它对令牌的数量很敏感(你真的需要在每次增加后检查是否点击了end())。如果您要使用这些奇怪的步骤和边界来迭代令牌,只需将令牌复制到可以使用随机访问迭代器的其他容器(如deque)中可能是有意义的 - 代码可能会干净得多。 您的第一种方法在将 begin() 返回的迭代器与 end() 进行比较之前递增它,当没有令牌时,它将具有未定义的行为 - 可以通过控制 if 语句轻松修复 @987654335 @循环。

以上是关于c ++迭代器循环与索引循环的主要内容,如果未能解决你的问题,请参考以下文章

python 迭代器与生成器

第五篇Python之迭代器与生成器

[Python] 迭代器是什么?你每天在用的for循环都依赖它!

python基础之循环与迭代器

迭代器

迭代器和生成器