請問C++11有哪些新特性?
- auto關鍵字:編譯器可以根據初始值自動推導出類型。但是不能用于函數傳參以及數組類型的推導
- nullptr關鍵字:nullptr是一種特殊類型的字面值,它可以被轉換成任意其它的指針類型;而NULL一般被宏定義為0,在遇到重載時可能會出現問題。
- 智能指針:C++11新增了std::shared_ptr、std::weak_ptr等類型的智能指針,用于解決內存管理的問題。
- 初始化列表:使用初始化列表來對類進行初始化
- 右值引用:基于右值引用可以實現移動語義和完美轉發,消除兩個對象交互時不必要的對象拷貝,節省運算存儲資源,提高效率
- atomic原子操作用于多線程資源互斥操作
- 新增STL容器array以及tuple



請你詳細介紹一下C++11中的可變參數模板、右值引用和lambda這幾個新特性。
可變參數模板:
- C++11的可變參數模板,對參數進行了高度泛化,可以表示任意數目、任意類型的參數,其語法為:在class或typename后面帶上省略號”。
例如:
Template<class ... T>
void func(T ... args)
{
cout<<”num is”<<sizeof ...(args)<<endl;
}
- func();//args不含任何參數
- func(1);//args包含一個int類型的實參
- func(1,2.0)//args包含一個int一個double類型的實參
- 其中T叫做模板參數包,args叫做函數參數包
省略號作用如下:
- 1)聲明一個包含0到任意個模板參數的參數包
- 2)在模板定義得右邊,可以將參數包展成一個個獨立的參數
- C++11可以使用遞歸函數的方式展開參數包,獲得可變參數的每個值。通過遞歸函數展開參數包,需要提供一個參數包展開的函數和一個遞歸終止函數。例如:
#include using namespace std;// 最終遞歸函數void print()
{
cout << "empty" << endl;
}// 展開函數
template void print(T head, Args... args)
{
cout << head << ","; print(args...);
}
int main()
{
print(1, 2, 3, 4); return 0;
}
- 參數包Args ...在展開的過程中遞歸調用自己,每調用一次參數包中的參數就會少一個,直到所有參數都展開為止。當沒有參數時就會調用非模板函數printf終止遞歸過程。
補充
#include <iostream>
#include <vector>template <class T>
class Stack{
private:std::vector<T> elements;//元素
public:void push(T const&);//入棧void pop();//出棧T top() const;//返回棧頂元素bool empty() const{//如果為空返回真return elements.empty();}
};template<class T>
void Stack<T>::push(const T &elem) {//追加元素的副本elements.template emplace_back(elem);
}
template<class T>
void Stack<T>::pop() {if (elements.empty()){throw std::out_of_range("Stack<>::pop():empty stack");}//刪除元素elements.pop_back();
}template <class T>
T Stack<T>::top() const {if (elements.empty()){throw std::out_of_range("Stack<>::top():empty stack");}//返回第一個元素的副本return elements.back();
}int main(int argc,char* argv[])
{try {Stack<int> int_stack{};Stack<std::string> string_stack{};//操作 int 類型的棧int_stack.push(7);std::cout << int_stack.top() << std::endl;//操作 string 類型的棧string_stack.push("hello");std::cout << string_stack.top() << std::endl;string_stack.pop();string_stack.pop();} catch (std::exception const&ex) {std::cerr << "Exception:" << ex.what() << std::endl;return -1;}return 0;
}
右值引用:
- C++中,左值通常指可以取地址,有名字的值就是左值,而不能取地址,沒有名字的就是右值。而在指C++11中,右值是由兩個概念構成,將亡值和純右值。純右值是用于識別臨時變量和一些不跟對象關聯的值,比如1+3產生的臨時變量值,2、true等,而將亡值通常是指具有轉移語義的對象,比如返回右值引用T&&的函數返回值等。
- C++11中,右值引用就是對一個右值進行引用的類型。由于右值通常不具有名字,所以我們一般只能通過右值表達式獲得其引用
- 基于右值引用可以實現轉移語義和完美轉發新特性。
- 參見原文
Lambda表達式
- Lambda表達式定義一個匿名函數,并且可以捕獲一定范圍內的變量,其定義如下:
- [capture](params)mutable->return-type{statement}
- [capture]:捕獲列表,捕獲上下文變量以供lambda使用。同時[]是lambda寅初復,編譯器根據該符號來判斷接下來代碼是否是lambda函數。
- (Params):參數列表,與普通函數的參數列表一致,如果不需要傳遞參數,則可以連通括號一起省略。
- mutable是修飾符,默認情況下lambda函數總是一個const函數,Mutable可以取消其常量性。在使用該修飾符時,參數列表不可省略。
- ->return-type:返回類型是返回值類型
- {statement}:函數體,內容與普通函數一樣,除了可以使用參數之外,還可以使用所捕獲的變量。
- Lambda表達式與普通函數最大的區別就是其可以通過捕獲列表訪問一些上下文中的數據。其形式如下:

- Lambda的類型被定義為“閉包”的類,其通常用于STL庫中,在某些場景下可用于簡化仿函數的使用,同時Lambda作為局部函數,也會提高復雜代碼的開發加速,輕松在函數內重用代碼,無須費心設計接口。