hyp*_*not 5 c++ boost iterator stl
对于一个非常简单的事情,例如在向量中打印每个元素,在C++中使用的更好的方法是什么?
我一直在用这个:
for (vector<int>::iterator i = values.begin(); i != values.end(); ++i)
Run Code Online (Sandbox Code Playgroud)
之前,但在我看到的Boost :: filesystem示例之一:
for (vec::const_iterator it(v.begin()), it_end(v.end()); it != it_end; ++it)
Run Code Online (Sandbox Code Playgroud)
对我来说,它看起来更复杂,我不明白为什么它比我一直使用的更好.
你能告诉我为什么这个版本会更好吗?或者对于像矢量打印元素这样的简单事情无关紧要?
是否i != values.end()
使迭代慢?
还是const_iterator
vs iterator
?const_iterator在这样的循环中更快吗?
Ker*_* SB 10
Foo x = y;
并且Foo x(y);
是等价的,所以请根据自己的喜好使用.
end
无论如何,提升出循环可能是也可能不是编译器会做的事情,无论如何,它明确表示容器端没有改变.
如果你不打算修改元素,请使用const-iterators,因为这就是它们的意思.
for (MyVec::const_iterator it = v.begin(), end = v.end(); it != end; ++it)
{
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
在C++ 0x中,使用auto
+ cbegin()
:
for (auto it = v.cbegin(), end = v.cend(); it != end; ++it)
Run Code Online (Sandbox Code Playgroud)
(也许你想使用现成的容器漂亮打印机?)
for (vector<int>::iterator i = values.begin(); i != values.end(); ++i)
Run Code Online (Sandbox Code Playgroud)
... ... VS
for (vec::const_iterator it(v.begin()), it_end(v.end()); it != it_end; ++it)
Run Code Online (Sandbox Code Playgroud)
对我来说[后者,在增强中看到]看起来更复杂,我不明白为什么它比我一直使用的更好.
我会说,对于那些没有某些特定理由喜欢后者的人来说,它会使人们感到歪曲,这看起来会更复杂.但让我们继续讨论为什么它会更好......
你能告诉我为什么这个版本会更好吗?或者对于像矢量打印元素这样的简单事情无关紧要?i!= values.end()会使迭代变慢吗?
it_end
性能:作为循环的开始只it_end
获取end()
一次值.对于计算end()
费用过高的任何容器,只调用一次可以节省CPU时间.对于任何中途不错的真实C++标准库,所有end()
函数都不执行任何计算,并且可以内联以获得相同的性能.在实践中,除非有可能需要放入一个非标准的容器,这个容器的end()
功能更加昂贵,所以end()
在优化的代码中明确地"缓存"没有任何好处.
这是有趣的,因为这意味着对于vector
该size()
可能需要小的计算-概念性地减去begin()
从end()
再除以sizeof(value_type)
(编译器刻度隐期间指针运算由大小),例如GCC 4.5.2:
size_type size() const
{ return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); }
维护:如果代码演变为插入或擦除循环内的元素(显然是迭代器本身没有失效 - 对于映射/集合/列表等是合理的),这是另一个维护点(因此错误 -如果缓存的end()
值也需要明确重新计算,则为俯卧.
一个小细节,但这里vec
必须是一个typedef
,而恕我直言通常最好使用typedef作为容器,因为它放松了容器类型的耦合,并且可以访问迭代器类型.
type identifier(expr)
风格和纪录片重点:type identifier(expr)
更直接地指示构造函数调用type identifier = expr
,这是一些人喜欢这种形式的主要原因.我通常更喜欢后者,因为我喜欢强调赋值感 ...它在视觉上是明确的,而函数调用符号用于很多事情.
近等价: 对于大多数类,无论如何都调用相同的构造函数,但如果type
有类型的显式构造函数expr
,则在=
使用时将传递它.更糟糕的是,一些其他转换可能允许使用不太理想的构造函数.例如,X x = 3.14;
会传递explicit X::X(double);
给匹配X::X(int)
- 你可能会得到一个不那么精确(或者只是完全错误)的结果 - 但是我还没有被这样的问题所困扰,所以它非常理论化!
或者是const_iterator与迭代器?const_iterator在这样的循环中更快吗?
对于标准集装箱,const_iterator
并iterator
执行相同,但后者意味着你要为你遍历修改元素的能力.使用const_iterator
您不打算这样做的文档,编译器将捕获尝试修改的迭代器的任何矛盾用法.例如,当您打算增加迭代器本身时,您将无法意外地增加迭代器地址的值.
鉴于C++ 0x已在其他答案中提及 - 但只有auto
和cbegin
/ 的增量收益,cend
还有一个新的表示法支持:
for (const Foo& foo: container)
// use foo...
Run Code Online (Sandbox Code Playgroud)