問題描述
在以下代碼中:
std::vector<int> var;
for (int i = 0; i < var.size(); i++);
size()
成員函數是為每次循環迭代調用還是只調用一次?
Is the size()
member function called for each loop iteration, or only once?
推薦答案
理論上,每次都會調用,因為for循環:
In theory, it is called each time, since a for loop:
for(initialization; condition; increment)
body;
被擴展為類似
{
initialization;
while(condition)
{
body;
increment;
}
}
(注意大括號,因為初始化已經在內部范圍內)
(notice the curly braces, because initialization is already in an inner scope)
在實踐中,如果編譯器理解你的條件的一部分在循環的所有持續時間內是不變的,并且它沒有副作用,它可以足夠聰明將其移出.這通常使用 strlen
和類似的東西(編譯器很清楚)在沒有寫入其參數的循環中完成.
In practice, if the compiler understands that a piece of your condition is invariant through all the duration of the loop and it does not have side-effects, it can be smart enough to move it out. This is routinely done with strlen
and things like that (that the compiler knows well) in loops where its argument isn't written.
但是必須注意,最后一個條件并不總是很容易證明;一般來說,如果容器是函數的本地容器并且從不傳遞給外部函數,那么這很容易;如果容器不是本地的(例如它是通過引用傳遞的 - 即使它是 const
)并且循環體包含對其他函數的調用,編譯器通常必須假設這些函數可能會改變它,從而阻塞吊裝長度計算.
However it must be noted that this last condition isn't always trivial to prove; in general, it's easy if the container is local to the function and is never passed to external functions; if the container is not local (e.g. it's passed by reference - even if it's const
) and the loop body contains calls to other functions, the compiler often has to assume that such functions may alter it, thus blocking the hoisting of the length calculation.
如果您知道條件的一部分評估起來昂貴",那么手動進行優化是值得的(而這種條件通常不是,因為它通常歸結為指針減法,這幾乎肯定是內聯的).
Doing that optimization by hand is worthy if you know that a part of your condition is "expensive" to evaluate (and such condition usually isn't, since it usually boils down to a pointer subtraction, which is almost surely inlined).
正如其他人所說,一般來說,容器最好使用迭代器,但對于 vector
s,它不是那么重要,因為通過 operator[]
保證為 O(1);實際上,對于向量,它通常是指針和(向量基數+索引)和取消引用與指針增量(前元素+1)和迭代器的取消引用.由于目標地址仍然相同,我認為您無法從緩存局部性方面從迭代器中獲得任何東西(即使如此,如果您不是在緊密循環中遍歷大數組,您甚至不應該注意到這樣的某種改進).
as others said, in general with containers it's better to use iterators, but for vector
s it's not so important, because random access to elements via operator[]
is guaranteed to be O(1); actually with vectors it usually is a pointer sum (vector base+index) and dereference vs the pointer increment (preceding element+1) and dereference of iterators. Since the target address is still the same, I don't think that you can gain something from iterators in terms of cache locality (and even if so, if you're not walking big arrays in tight loops you shouldn't even notice such kind of improvements).
對于列表和其他容器,相反,使用迭代器而不是隨機訪問可能真的很重要,因為使用隨機訪問可能意味著每次遍歷列表,而增加迭代器只是一個指針解引用.
For lists and other containers, instead, using iterators instead of random access can be really important, since using random access may mean walk every time the list, while incrementing an iterator is just a pointer dereference.
這篇關于C++ 循環中 vector::size() 的性能問題的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!