這要是對以下幾種在c++裏的 for-range-loop做一個總結
for(auto e : container)
for(auto &e : container)
for(const auto &e : container)
for(auto && e : container)
這裏主要是參考 ref [1] stackoverflow裏的類容,他總結的很好,我這裏做個備份
核心思想是
和函數的參數一樣,Same consideration applies as for function arguments
簡單解釋
- for(auto e : container)
這會使用一個 copy-constructor函數,構造一個副本,也就是說 e,僅僅是container中的一個copy
test-code 見ref1 - for(const auto & e:container),for(auto &e : container)
這兩者的區別在於 const 不能在for-loop中更改 e,兩者的開銷(通常意義下,取決於copy-construct的開銷)都會比 1低, - for(auto &&e : container)
這個語法我也是第一次遇見,主要給一些proxy-iterator使用的,
例如vector<bool>
STL將其設計爲一個bool一個bit 所以是沒法refrence到它的地址的(cpu按byte尋址),如果用for(auto & e: container)
會出現編譯錯誤
不過, 這種語法是兼容for(auto & e:container)
,並且時間開銷接近(見後文的時間測試)
使用總結
- For observing mode,即僅僅是read-only的情況
- 通常使用
for(const auto &e:container)
- 例外,對於copy-cheap的類型(e.g. int,double,…,value type),
for(auto e:container)
- 通常使用
- For modifying mode,需要再遍歷過程中modify 數據的情況
- 通常使用
for(auto & e :container)
- 對於 proxy-iterator 採用
for(auto && e: container)
- 通常使用
這裏不得不感慨 cpp
這是最難的語言,例外如此多,一點也不general,一點也不generic…
有沒有更簡單一些的規則呢? 更general一些的,有的
- For observing
for(const auto &e : container)
不管它是不是copy-cheap,也不管它是不是value-type,(實際測試中(int,long long,double) 使用auto e仍舊會比const auto &e 慢一些,測試見後文) - For modifying
for(auto && e: container)
就ok 了,因爲這兩者 行爲 (並未看過底層是否等價)等價,並且時間也接近
時間測試
- copy-construct 在
vector<string>,every string'length is equal to 100
-
測試代碼 github
-
測試結果
auto e : 0.132257s const auto & e: 0.0180348s auto && e : 0.0188524s
-
- 值類型(int,long long,double) 測試
- 測試代碼 github
- 測試結果
for-type | int(s) | long long(s) | double(s) |
---|---|---|---|
auto e | 0.0932 | 0.0924 | 0.0933 |
const auto& e | 0.0884 | 0.0861 | 0.0875 |
auto && e | 0.0903 | 0.0872 | 0.0864 |
需要注意的是測試代碼僅僅是測試的遍歷,沒有訪問過程,如果考慮訪問尋址的開銷,那麼對於value type based on refrence 可能會開銷更多的時間.
refrence
版權聲明
本作品爲作者原創文章,採用知識共享署名-非商業性使用-相同方式共享 4.0 國際許可協議
作者: taotao
轉載請保留此版權聲明,並註明出處