C++11中一些常見的特性
C++11標準由國際標準化組織(ISO)和國際電工委員會(IEC)旗下的C++標準委員會(ISO/IEC JTC1/SC22/WG21)於2011年8月12日公佈 [2] ,並於2011年9月出版。2012年2月28日的國際標準草案(N3376)是最接近於C++11標準的草案(僅編輯上的修正)。此次標準為C++98釋出後13年來第一次重大修正。
一、auto型別說明符
auto型別說明符能夠讓編譯器替我們去分析表示式所屬的型別。所以,auto定義的變數必須有初始值。
需要注意的是,auto一般會忽略頂層const,同時底層const則會保留下來。
#include <iostream> using namespace std; int main(void) { int i = 5, m = 3; const int j = i, &k = j; auto b = j;//b是一個整數(j的頂層const特性被忽略調了) b = 6;//可以對b進行修改 auto c = k;//c是一個整數(k是j的別名,j本身是一個頂層const) c = 8;//可以對c進行修改 auto d = &i;//d是一個整型指標 auto e = &j;//e是一個指向整數常量的指標(屬於底層const) *e = 4;//錯誤,e是指向整數常量的指標 system("pause"); return 0; }
二、decltype型別指示符
有時會遇到這種情況:希望從表示式的型別推斷出要定義的變數的型別,但是不想用該表示式的值初始化變數。decltype的作用就是選擇並返回運算元的資料型別。在此過程中,編譯器分析表示式並得到它的型別,卻不實際計算表示式的值。
#include <iostream> using namespace std; int fun() { int num = 6; return num; } int main(void) { int i = 6; decltype(fun()) result = i; //result的型別就是函式fun()的返回型別 cout << result << endl; system("pause"); return 0; }
其次,decltype處理頂層const和引用的方式與auto有區別。如果decltype使用的表示式是一個變數,則decltype返回該變數的型別(包括頂層const和引用在內)
#include <iostream> using namespace std; int main(void) { const int i = 3, &j = i; decltype(i) a = 4;//a的型別是const int //a = 5;//錯誤 decltype(j) b = a;//b的型別是const int&,b繫結到變數x decltype(j) c;//錯誤:c是一個引用,必須初始化 system("pause"); return 0; }
三、範圍for語句
C++11 新標準引入了一種簡單的for語句,這種語句可以遍歷容器或其它序列的元素。
#include <iostream>
#include<vector>
using namespace std;
int main(void)
{
vector<int> v = { 1,2,3,4,5 };
for (auto i : v)
cout << i << " ";
return 0;
}
四、匿名函式lambda
我們可以向一個演算法傳遞任何類別的可呼叫物件。對於一個物件或一個表示式,如果可以對其使用呼叫運算子,則稱它為可呼叫的。也就是說,如果e是一個可呼叫的表示式,則可以編寫e(args)。
#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
bool cmp(int a, int b)
{
return a < b;
}
int main(void)
{
vector<int> v = { 1,3,5,4,6 };
for (auto i : v)
cout << i << " ";
cout << endl;
sort(v.begin(), v.end(), [](int a, int b) -> bool { return a < b; }); // Lambda表示式
for (auto i : v)
cout << i << " ";
cout << endl;
system("pause");
return 0;
}
五、尾置返回型別
尾置返回型別是C++11新標準中簡化宣告函式的方法。常規情況下,如果我們想要定義一個返回陣列指標的函式,是比較麻煩的,但通過使用尾置返回型別,就變得容易許多。
(1)常規方法:宣告一個返回陣列長度為10的整形陣列
int (*func(int i))[10];
(2)使用typedef或using關鍵字
typedef int arrT[10];
//等價於 using arrT = int[10];
arrT* func(int i); //宣告func函式
(3)使用尾置返回型別
auto func(int) -> int(*)[10]; //宣告Func函式
此外,我們還可以在模板中使用尾置返回型別
//示例中模板接受一對迭代器和返回序列中的一個解引用
template <typename It>
auto fcn(It beg, It end) -> decltype(*beg)
{
return *beg; //返回序列中一個元素的引用
}
六、nullptr
#include <iostream>
using namespace std;
void func(void* t)
{
cout << "func1" << endl;
}
void func(int i)
{
cout << "func2" << endl;
}
int main()
{
func(NULL);
func(nullptr);
system("pause");
return 0;
}
看起來NULL和nullptr都是代表空指標,但是NULL在過載函式的時候卻匹配到了引數為int的那個版本。
這是因為在C++中,NULL的定義一般是這樣的:
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void*)0)
#endif // __cplusplus
可以看到,其實NULL在C++中就是代表著0,這是因為在C++中void* 型別是不允許隱式轉換成其他型別的,所以C++中用0來代表空指標,但是在過載整形的情況下,會出現上述的問題。所以,C++11加入了nullptr,可以保證在任何情況下都代表空指標,而不會出現上述的情況,因此,以後應該使用nullptr。
七、override(覆蓋)
函式重寫是指子類重新定義基類的虛擬函式。特徵是:
如果派生類在虛擬函式宣告時使用了override描述符,那麼該函式必須過載其基類中的同名函式,否則程式碼將無法通過編譯。
(1)不在同一個作用域(分別位於派生類與基類);
(2)函式名字相同;
(3)引數相同;
(4)基類函式必須有 virtual 關鍵字,不能有 static 。
(5)返回值相同,否則報錯;
(6)重寫函式的訪問修飾符可以不同;
#include <iostream>
using namespace std;
struct Base
{
virtual void wangkai();
virtual void nangua();
virtual void liyuan(int g) = 0;
virtual void pangge() const;
void huowei();
};
void Base::wangkai()
{
cout << "wangkai" << endl;
}
void Base::nangua()
{
cout << "nangua" << endl;
}
void Base::pangge() const
{
cout << "pangge" << endl;
}
void Base::huowei()
{
cout << "huowei" << endl;
}
struct Derived:public Base
{
virtual void wangkai() override;
void nanguaN();
virtual void liyuan(int g) override;
virtual void pangge() const override;
//void huowei();//非虛擬函式不可以使用override
};
void Derived::wangkai()
{
cout << "wangkai666" << endl;
}
void Derived::liyuan(int g)
{
cout << "liyuan" << endl;
}
void Derived::nanguaN()
{
cout << "nanguaN" << endl;
}
void Derived::pangge() const
{
cout << "pangge" << endl;
}
/*
void Derived::huowei()
{
cout << "huowei666" << endl;
}
*/
int main(void)
{
Derived d1;
d1.nanguaN();
d1.nangua();
d1.wangkai();
d1.huowei();
system("pause");
return 0;
}
八、shared_ptr類
在C++中,動態記憶體的管理是通過一對運算子來完成的,即new和delete。動態記憶體的使用容易出問題,比如忘記釋放記憶體、釋放正在使用的指標等。新的標準庫提供了兩種智慧指標型別來管理動態物件。它們能夠自動釋放所指向的物件。shared_ptr允許多個指標指向同一個物件;unique_ptr則”獨佔“所指的物件。它們都定義在memory標頭檔案中。
參照另一篇部落格智慧指標