这是一个简单的吸气剂吗?或者每次计算?
如果我有这样的for循环:
for (int i = 0; i < myVector.size(); i++) { }
我只需要使用一次大小,在循环之前计算一次并将其存储在变量中会更好吗?或者size()只是一个简单的吸气剂,它会有什么不同?
答案 0 :(得分:6)
这是实现定义的。假设实现想要提供有效的标准库,那么两个最可能的实现是:
无论如何,标准要求复杂性是恒定的,你不应该真的担心它。此外,编译器经常进行优化,以便自行存储大小。
答案 1 :(得分:5)
使用迭代器而不是这样的循环来获得更大的灵活性和基因性:
std::vector<int>::const_iterator iter = myVector.begin();
for(iter; iter!= myVector.end(); ++iter)
{
}
这确保了如果在开发的后期更改容器,则代码的耦合程度会降低。
答案 2 :(得分:1)
在我看过的每一个实现中,它都是每次计算的 - 在O(1)中 - 通过从结尾开始减去。所以,它几乎没有什么区别。编译器可能会或可能不会优化“计算”,但时间是如此微不足道,以至于除了最绝望的情况之外的所有人都无关紧要。
使用你认为更可维护的东西:无论读取效果如何,最好地定位逻辑等等。可以说值得注意的是,在使用size()时,即使内部有删除或插入,也要确保准确跟踪向量的结尾循环体,因此可能有功能上的原因要求(或避免)重复调用size()。
请注意,对于STL列表,size()不是常量时间 - 它是线性的。
答案 3 :(得分:1)
http://www.cplusplus.com/reference/stl/vector/size/表明操作的复杂性是不变的。这意味着每次调用size()
时都不会重新计算大小,或者在大多数情况下开销可以忽略不计。所以在你的代码中使用它就好了:这不会是你代码的瓶颈。 (除非这是一个紧密的内循环,每次优化都会带来很多。)
此外,如果要在循环内更改矢量,您将会更安全(但不是完全安全!)。
答案 4 :(得分:0)
如果你看一下vector :: size()的实现
size_type size() const
{ // return length of sequence
return (_Mylast - _Myfirst);
}
其中_Mylast和_Myfirst是指针。
它只是一个指针算术,应该是一个原子操作。因此它不应该是一个开销!
答案 5 :(得分:0)
也许您实际上想知道编译器是否可以确定size()
函数返回的值永远不会改变并且将其提升它。虽然这看似合理,但编译器必须能够证明提升产生与您编写的版本完全相同的行为(即“每次都调用”size()
),并且有限制编译器可以看到多远,或者实际上可以证明这有多远。
因此,如果您知道没有更改容器的大小,则应手动编写提升机:
// index version:
for (std::size_t i = 0; end = v.size(); i != end; ++i) { work_with(v[i]); }
// iterator version:
for (auto it = v.begin(), end = v.end(); it != end; ++it) { work_with(*it); }
对std::vector::size()
的调用具有恒定的复杂性,即它们的成本与向量中的元素数量无关,但仍可能存在成本。在最好的情况下,你只是读取一个变量(所以在一个副本的提升和非提升版本的循环中没有区别),但是实现执行指针减法也是可行的。 / p>
答案 6 :(得分:0)
为size()
计算std::vector
需要恒定的时间,但计算可能比两个指针之间的差异更大。虽然这似乎是一种廉价的计算,但它增加了对可用寄存器的限制。此外,std::vector
的其他实现在size()
中需要付出更多努力,但会使其他操作更有效。
例如,对于许多用例,最好只用一个指向范围起点的指针表示std::vector
,并将控制数据放在此范围之前。奇怪的是,这种情况发生在使用数组分配分配的内存通常是如何布局的。控制数据将包含两个指针(一个指向范围的末尾,另一个指向容量)。在这种情况下获得大小包括地址调整(虽然具有固定大小),指针取消引用和减法。仍然不是很多但是你在[紧]循环中做的越少,它运行得越快(在大多数情况下)。
结果是:除非容器正在改变其大小,否则只需获取size()
和end()
一次。如果它正在改变大小,它取决于容器的类型是否应该重新计算东西:例如对于std::list
你不需要再次获得end()
(并且你根本不需要得到它的size()
。)我似乎记得斯科特迈耶斯在“有效STL”中讨论过这个话题,但我不记得他是否说过我刚做过的事(或者他是不是错了;)。