轉向Modern C++
優先使用auto推導類型而非顯示類型聲明
auto變量需要在聲明時進行初始化
int x1; // 未初始化的int變量,值的不確定的,可能爲0,也可能是別的值
auto x2; // 錯誤,需要初始化
auto x3 = 0; // 完美
auto使變量的聲明變得簡單,甚至僅僅被編譯器知道的類型
auto dereUPLess = [](const std::unique_ptr<Widget>& p1,
const std::unique_ptr<Widget>& p2)
{ return *p1 < *p2; }
auto可以避免類型的截斷
std::vector<int> vec;
unsigned sz = vec.size(); // size()的返回類型是std::vector<int>::size_type,32位機器上,unsigned和std::vector<int>::size_type都是32bit的,然而64位機器上,unsigned是32bit的,std::vector<int>::size_type卻是64bit的,這回導致返回類型的截斷
auto sz = vec.size(); // sz的類型是std::vector<int>::size_type,不會導致截斷
總結
auto是一個可選項,不是必須項。如果根據你的專業判斷,使用顯式的類型聲明比使用auto會使你的代碼更加清晰或者更好維護,或者在其他方面更有優勢, 你可以繼續使用顯式的類型聲明。這是一個新人易學,老人已用的新特性。
優先使用nullptr而不是0或者NULL
0字面上是一個int類型,而不是指針。C++掃描到一個0,但是發現在上下文中僅有一個指針使用了它,於是編譯器勉強將0解釋爲空指針。NULL也是同樣的道理。
nullprt不在是一個整數類型,它是一個std::nullptr_t類型,std::nullptr_t類型可以隱式的轉換爲任何原始的指針類型,因此可以認爲nullptr指向任何類型的指針。
nullptr可以提高代碼的清晰度
auto retTpype = find();
if (retTpype == 0)
{
/* code */
}
if (retTpype == nullprt)
{
/* code */
}
使用nullptr就沒有歧義了,也能明顯的看出retTpype是一個指針類型。
有限使用別名而不是typedef
typedef void (*FP)(int, const std::string);
using FP = void(*)(int, const std::string);
在所有能使用typedef的地方都可以使用別名,但是typedef不支持模板化,而別名支持
模板別名避免了::type後綴,在模板中,typedef還經常要求使用typename
使用作用域限制的enum而不是無作用域的enum
有作用域限制的enum可以減少命名空間的污染
enum ColorNoScoped
{
black, white, red
};
auto white = false; // 錯誤,因爲white在此作用域中已經被定義
enum class ColorScoped
{
black, white, red
};
auto white = false; // 可以
ColorScoped c = ColorScoped::white;
auto cw = ColorScoped::white;
有作用域限制的enum可以避免一些無必要的隱式類型轉換
enum ColorNoScoped
{
black, white, red
};
ColorNoScoped c = red;
if (c < 14.5)
{
/* code */ // 可以
}
enum class ColorScoped
{
black, white, red
};
auto c = ColorScoped::white;
if (c < 14.5) // 錯誤
{
/* code */
}
if (static_cast<double>(c) < 14.5) // 正確
{
/* code */
}
有作用域限制的enum可以被提前聲明,而無作用域限制的enum不可以
enum ColorNoScoped; // 錯誤
enum class ColorScoped; // 可以
優先使用delete關鍵字刪除函數而不是private而不不實現的空函數
template <class charT, class traits = char_traits<charT> >
class basic_ios : public ios_base {
public:
basic_ios(const basic_ios& ) = delete;
basic_ios& operator=(const basic_ios&) = delete;
/* code */
};
使用override關鍵字聲明覆蓋函數
對於派生類中覆蓋體都聲明爲 override,不僅僅可以讓編譯器在應該要去覆蓋基類中函數而沒有去覆蓋的時候可以警告你。它還可以幫助你預估一下更改基類裏的虛函數的標識符可能會 引起的後果。
優先使用const_iterator而不是iterator
std::std::vector<int> values;
auto it = std::find(values.cbegin(), values.cend(), 16);
values.insert(it, 32);