1. 程式人生 > >C++11中一些常見的特性

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)使用typedefusing關鍵字

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標頭檔案中。
參照另一篇部落格智慧指標