隨着Vsisual Studio 2013 RC版的放出,之前承諾的對C++ 11語法支持已經全部完成,本文是C++ 11中我喜歡的語法系列的最后一部分(一),(二)。
非靜態成員直接初始化
在C++ 03的時候,非靜態成員變量只能在對象的構造函數里初始化,例如:
struct A
{
int m;
A() : m (7) { }
};
當對象成員比較多的時候,這個對象成員的初始化是非常難看的。尤其是在構造函數較多的情況下,由於C++ 03不支持委托構造函數,這一大堆的成員需要在每一個構造函數中初始化一遍,是十分冗繁而容易出錯的。
在C++ 11中,非靜態成員也能以靜態成員那種方式直接初始化的,這樣就直觀的多了:
struct A
{
int m = 7;
};
啟用和禁止默認函數
在C++中,編譯器會生成一些默認函數,例如對於任意一個類A,如果不想編寫上述函數,C++編譯器將自動為A產生四個缺省的函數,如
-
A(void); // 缺省的無參數構造函數
-
A(const A &a); // 缺省的拷貝構造函數
-
~A(void); // 缺省的析構函數
-
A & operate =(const A &a); // 缺省的賦值函數
在C++ 11中,支持通過 default 和 delete 兩個關鍵字來管理這默認函數。delete意為禁止默認函數,default則使用默認函數。
例如,當我們自定義你空構造函數時,編譯器就不會給我們生成缺省無參構造函數,此時則可以通過= default來讓編譯器產生默認構造函數。
struct A
{
A() = default;
A(int n) {}
};
至於= delete,一個比較典型的用途是可以定義一個不可拷貝的對象,如:
struct NoCopy
{
NoCopy & operator =(const NoCopy &) = delete;
NoCopy(const NoCopy &) = delete;
};
另外,= delete也可以用於禁止那些隱式轉換而執行的函數,例如:
struct A
{
void foo(int k){}
void foo(double k) = delete;
};
這樣,類似a.foo(3.2)之類的調用就會有編譯錯誤(話說,應該像C#那樣天生報編譯錯誤才更為合理)。
類型別名
雖然自C語言時代就支持通過typedef來為類型起別名,但typedef對函數指針起別名顯得比較難看,並且不支持模板。因此,在C++ 11種新增了using為對象起別名的語法:
// typedef std::ios_base::fmtflags flags;
using flags = std::ios_base::fmtflags;
// typedef void (*func)(int, int);
using func = void(*) (int, int);
template<class T> using ptr = T*;
//'ptr<T>' 等價於 T 的指針
ptr<int> x;