C11簡潔之道 迴圈的改善

2022-05-07 00:51:08 字數 2222 閱讀 2732

在c++98/03中,通過for迴圈對乙個容器進行遍歷,一般有兩種方法,常規的for迴圈,或者使用中的for_each方法。

for迴圈遍歷:

void func(void

)}

for_each方法:

void vfunccall(int

n)void func2(void

)

for_each相比一般的for迴圈,只需關注容器元素的型別,但是都是基於範圍的迴圈,必須顯示的給出容器的開始(begin)和結束(end)。c++11中改善了這種遍歷方式,不再需要給出容器的兩端,迴圈會自動根據容器的範圍自動的展開,在迴圈中遮蔽了迭代器的遍歷細節,直接抽取容器中的元素進行運算。我們來看c++11中是怎麼遍歷容器的:

void func(void

)}

是不是很簡潔,n表示arr中的乙個元素, auto會被編譯器自動推導出型別,此例中被推導為vector中的int型別。當然,也可以直接寫出型別:

std::vectorarr;

for(int n : arr)

同時,這種迴圈中,冒號前面的變數支援隱式轉換的,因此在使用時需要注意:

std::vectorarr;

for(char c : arr) //

int會被隱式轉換為char

在這種迴圈中,我們都是唯讀方式來遍歷容器的,如果需要改變容器中的值,我們需要加上引用,如果是只希望遍歷而不是修改,我們可以使用const auto & 來定義n的型別,這樣對於複製負擔比較大的容器元素(std::vector陣列等)也可以無耗的進行遍歷。

std::vectorarr;

for(auto &n : arr)

我們來看使用範圍的for迴圈和普通的for迴圈有什麼區別:

std::mapstring, int> mmsi_test = , , };

//一般情況的for迴圈

for(auto it = mmsi_test.begin(); it != mmsi_test.end(); ++it)

//基於範圍的for迴圈

for(auto val : mmsi_test)

可以看出:

如果我們要改變某些容器元素的值,通過auto &可以解決大多數問題,但是某些特殊容器並不能達到我們預期的結果。比如我們希望在迴圈中對set的值進行修改,但是set的內部元素的值是可讀的----由set容器的特性決定的,因此for迴圈中的auto &會被推導為const xx &。同樣基於範圍的map遍歷一樣,for迴圈得到的std::pair引用,是不能修改first的。

void func(void);

for(auto &val : ss)

}

我們先來看一段**,測試一下c++11中的迴圈對於容器的訪問頻率。

#include #include 

std::vector

g_arr = ;

std::vector

& func(void

)int main(void

)

return0;

}

程式的執行結果:

我們可以從結果中看出,不論基於範圍的for迴圈迭代了多少次,func()只在第一次迭代之前被呼叫,在迴圈之前就確定好迭代的範圍,而不是在每次迭代之前都去呼叫一次end()。所以可以得出結論:基於範圍的for迴圈,冒號後面的表示式只會被執行一次。

那麼我們來看如果在基於範圍的for迴圈中修改容器會出現什麼情況:

#include #include 

int main(void);

for(auto val : arr)

return0;

}

在centos6.7 64位系統執行結果:

從結果看出,這並不是我們需要的結果,如果把vector換成list,結果又不一樣。

因為介於範圍的for迴圈其實是普通for迴圈的語法糖,同普通的迴圈一樣,在迭代時修改容器可能引起迭代器失效,導致一些意料之外的結果。由於我們這裡是沒法看到迭代器的,所以在基於範圍的for迴圈中修改容器到底會造成什麼樣的影響非常困難。

C11簡潔之道 tupe元祖

tuple元組是乙個固定大小不同型別的值的集合,是泛化的std pair。我們也可以把它當作乙個通用的結構體來使用,不需要建立結構體有獲取結構體特徵,在某些情況可以取代結構體,使程式更簡潔 直觀。tuple在c 11中使用簡單,但是往往要和模板元的一些技巧結合使用。tuplechar int tp ...

C11建構函式的改善

委託建構函式就是允許在同乙個類中乙個建構函式可以呼叫另乙個建構函式,從而在初始化時簡化變數的初始化。class ctest ctest int a,int b ctest int a,int b,int c ctest 這個例子表明,在成員變數眾多 變數的初始化比較複雜的情況下,建構函式的工作是重複...

(原創)用c 11實現簡潔的ScopeGuard

scopeguard的作用是確保資源面對異常時總能被成功釋放,就算沒有正常返回。慣用法讓我們在建構函式裡獲取資源,當因為異常或者正常作用域結束,那麼在析構函式裡釋放資源。總是能釋放資源。如果沒有異常丟擲則正常結束,只是有異常發生或者沒有正常退出時釋放資源。關於scopegaurd的概念想多了解一點的...