阿里巴巴面試題基礎(chǔ)篇 C++11

● 請問C++11有哪些新特性?

參考回答:

C++11 最常用的新特性如下:

auto關(guān)鍵字:編譯器可以根據(jù)初始值自動推導(dǎo)出類型。但是不能用于函數(shù)傳參以及數(shù)組類型的推導(dǎo)

nullptr關(guān)鍵字:nullptr是一種特殊類型的字面值,它可以被轉(zhuǎn)換成任意其它的指針類型;而NULL一般被宏定義為0,在遇到重載時可能會出現(xiàn)問題。

智能指針:C++11新增了std::shared_ptr、std::weak_ptr等類型的智能指針,用于解決內(nèi)存管理的問題。

初始化列表:使用初始化列表來對類進(jìn)行初始化

右值引用:基于右值引用可以實現(xiàn)移動語義和完美轉(zhuǎn)發(fā),消除兩個對象交互時不必要的對象拷貝,節(jié)省運算存儲資源,提高效率

atomic原子操作用于多線程資源互斥操作

新增STL容器array以及tuple

● 請你詳細(xì)介紹一下C++11中的可變參數(shù)模板、右值引用和lambda這幾個新特性。

參考回答:

可變參數(shù)模板:

C++11的可變參數(shù)模板,對參數(shù)進(jìn)行了高度泛化,可以表示任意數(shù)目、任意類型的參數(shù),其語法為:在class或typename后面帶上省略號”。

例如:

Template<class ... T>
void func(T ... args)
{
cout<<”num is”<<sizeof ...(args)<<endl;
}</pre>

func();//args不含任何參數(shù)

func(1);//args包含一個int類型的實參

func(1,2.0)//args包含一個int一個double類型的實參

其中T叫做模板參數(shù)包,args叫做函數(shù)參數(shù)包

省略號作用如下:

1)聲明一個包含0到任意個模板參數(shù)的參數(shù)包

2)在模板定義得右邊,可以將參數(shù)包展成一個個獨立的參數(shù)

C++11可以使用遞歸函數(shù)的方式展開參數(shù)包,獲得可變參數(shù)的每個值。通過遞歸函數(shù)展開參數(shù)包,需要提供一個參數(shù)包展開的函數(shù)和一個遞歸終止函數(shù)。例如:

include using namespace std;

// 最終遞歸函數(shù)

void print()

{

cout << "empty" << endl;

}

// 展開函數(shù)

template void print(T head, Args... args)
{
cout << head << ","; print(args...);
}
int main()
{
print(1, 2, 3, 4); return 0;
}</pre>

參數(shù)包Args ...在展開的過程中遞歸調(diào)用自己,沒調(diào)用一次參數(shù)包中的參數(shù)就會少一個,直到所有參數(shù)都展開為止。當(dāng)沒有參數(shù)時就會調(diào)用非模板函數(shù)printf終止遞歸過程。

右值引用:

C++中,左值通常指可以取地址,有名字的值就是左值,而不能取地址,沒有名字的就是右值。而在指C++11中,右值是由兩個概念構(gòu)成,將亡值和純右值。純右值是用于識別臨時變量和一些不跟對象關(guān)聯(lián)的值,比如1+3產(chǎn)生的臨時變量值,2、true等,而將亡值通常是指具有轉(zhuǎn)移語義的對象,比如返回右值引用T&&的函數(shù)返回值等。

C++11中,右值引用就是對一個右值進(jìn)行引用的類型。由于右值通常不具有名字,所以我們一般只能通過右值表達(dá)式獲得其引用,比如:

T && a=ReturnRvale();

假設(shè)ReturnRvalue()函數(shù)返回一個右值,那么上述語句聲明了一個名為a的右值引用,其值等于ReturnRvalue函數(shù)返回的臨時變量的值。

基于右值引用可以實現(xiàn)轉(zhuǎn)移語義和完美轉(zhuǎn)發(fā)新特性。

移動語義:

對于一個包含指針成員變量的類,由于編譯器默認(rèn)的拷貝構(gòu)造函數(shù)都是淺拷貝,所有我們一般需要通過實現(xiàn)深拷貝的拷貝構(gòu)造函數(shù),為指針成員分配新的內(nèi)存并進(jìn)行內(nèi)容拷貝,從而避免懸掛指針的問題。

但是如下列代碼所示:

image

當(dāng)類HasPtrMem包含一個成員函數(shù)GetTemp,其返回值類型是HasPtrMem,如果我們定義了深拷貝的拷貝構(gòu)造函數(shù),那么在調(diào)用該函數(shù)時需要調(diào)用兩次拷貝構(gòu)造函數(shù)。第一次是生成GetTemp函數(shù)返回時的臨時變量,第二次是將該返回值賦值給main函數(shù)中的變量a。與此對應(yīng)需要調(diào)用三次析構(gòu)函數(shù)來釋放內(nèi)存。

而在上述過程中,使用臨時變量構(gòu)造a時會調(diào)用拷貝構(gòu)造函數(shù)分配對內(nèi)存,而臨時對象在語句結(jié)束后會釋放它所使用的堆內(nèi)存。這樣重復(fù)申請和釋放內(nèi)存,在申請內(nèi)存較大時會嚴(yán)重影響性能。因此C++使用移動構(gòu)造函數(shù),從而保證使用臨時對象構(gòu)造a時不分配內(nèi)存,從而提高性能。

如下列代碼所示,移動構(gòu)造函數(shù)接收一個右值引用作為參數(shù),使用右值引用的參數(shù)初始化其指針成員變量。

image

其原理就是使用在構(gòu)造對象a時,使用h.d來初始化a,然后將臨時對象h的成員變量d指向nullptr,從而保證臨時變量析構(gòu)時不會釋放對內(nèi)存。

image

完美轉(zhuǎn)發(fā):

完美轉(zhuǎn)發(fā)是指在函數(shù)模板中,完全依照模板的參數(shù)的類型,將參數(shù)傳遞給函數(shù)模板中調(diào)用的另一個函數(shù),即傳入轉(zhuǎn)發(fā)函數(shù)的是左值對象,目標(biāo)函數(shù)就能獲得左值對象,轉(zhuǎn)發(fā)函數(shù)是右值對象,目標(biāo)函數(shù)就能獲得右值對象,而不產(chǎn)生額外的開銷。

因此轉(zhuǎn)發(fā)函數(shù)和目標(biāo)函數(shù)參數(shù)一般采用引用類型,從而避免拷貝的開銷。其次,由于目標(biāo)函數(shù)可能需要能夠既接受左值引用,又接受右值引用,所以考慮轉(zhuǎn)發(fā)也需要兼容這兩種類型。

C++11采用引用折疊的規(guī)則,結(jié)合新的模板推導(dǎo)規(guī)則實現(xiàn)完美轉(zhuǎn)發(fā)。其引用折疊規(guī)則如下:

image

因此,我們將轉(zhuǎn)發(fā)函數(shù)和目標(biāo)函數(shù)的參數(shù)都設(shè)置為右值引用類型,

image

當(dāng)傳入一個X類型的左值引用時,轉(zhuǎn)發(fā)函數(shù)將被實例為:

image

經(jīng)過引用折疊,變?yōu)椋?/p>

image

當(dāng)傳入一個X類型的右值引用時,轉(zhuǎn)發(fā)函數(shù)將被實例為:

image

經(jīng)過引用折疊,變?yōu)椋?/p>

image

除此之外,還可以使用forward()函數(shù)來完成左值引用到右值引用的轉(zhuǎn)換:

image

Lambda表達(dá)式:

Lambda表達(dá)式定義一個匿名函數(shù),并且可以捕獲一定范圍內(nèi)的變量,其定義如下:

capturemutable->return-type{statement}

其中,

[capture]:捕獲列表,捕獲上下文變量以供lambda使用。同時[]是lambda寅初復(fù),編譯器根據(jù)該符號來判斷接下來代碼是否是lambda函數(shù)。

(Params):參數(shù)列表,與普通函數(shù)的參數(shù)列表一致,如果不需要傳遞參數(shù),則可以連通括號一起省略。

mutable是修飾符,默認(rèn)情況下lambda函數(shù)總是一個const函數(shù),Mutable可以取消其常量性。在使用該修飾符時,參數(shù)列表不可省略。

->return-type:返回類型是返回值類型

{statement}:函數(shù)體,內(nèi)容與普通函數(shù)一樣,除了可以使用參數(shù)之外,還可以使用所捕獲的變量。

Lambda表達(dá)式與普通函數(shù)最大的區(qū)別就是其可以通過捕獲列表訪問一些上下文中的數(shù)據(jù)。其形式如下:

image

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


image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容