C++基礎面試題總結


1.面向對象的特征?
    封裝、繼承、多態。

2.一個C++源文件從文本到可執行文件經歷的過程?
    預處理階段:對源代碼文件中文件包含關系(頭文件)、預編譯語句(宏定義)進行分析和替換,生成預編譯文件
    編譯階段:將經過預處理后的預編譯文件轉換成特定匯編代碼(編譯原理相關,詞法分析、語法分析、語義分析等),生成匯編文件 
    匯編階段:將編譯階段生成的匯編文件轉化成機器碼,生成可重定位目標文件
    鏈接階段:將多個目標文件及所需要的庫打包連接成最終的可執行目標文件(或庫文件以供其他程序使用)

3.new和malloc的區別?
    new是一個操作符,而malloc()是一個庫函數。
    new會自動計算需分配的空間,malloc不行
    new會調用構造函數,malloc不會
    new是類型安全的,而malloc不是
    malloc/free要庫文件支持,new/delete則不要。
    new返回指定類型指針,malloc返回void*指針,需要強制類型轉換
    new可以被重載,malloc不能

4.虛函數是什么以及其作用?
    虛函數是允許被其子類重新定義的成員函數。可以實現用父類型別的指針指向其子類的實例,然后通過父類的指針調用實際子類的成員函數。有了虛函數,基類指針指向基類對象時就使用基類的成員(包括成員函數和成員變量),指向派生類對象時就使用派生類的成員,從而實現多態。注意:構造函數不能為虛函數,但是析構函數可以為虛函數,並且虛析構函數可以防止父類指針銷毀子類對象時不正常導致的內存泄漏。

5.虛函數表是什么?
    虛函數是通過一張虛函數表來實現的。簡稱為V-Table。如果一個類中包含虛函數(virtual修飾的函數),那么這個類就會包含一張虛函數表,虛函數表存儲的每一項是一個虛函數的地址。[這篇博客](https://blog.csdn.net/u012630961/article/details/81226351)簡單介紹了一下虛函數表的細節,個人覺得比較清晰,但是個別地方還需要仔細推敲消化。

6.什么函數不能聲明為虛函數?構造函數為什么不能為虛函數?
    普通函數(非成員函數)、構造函數、友元函數、靜態成員函數、內聯成員函數。
    當派生類在創建對象的時候會調用基類的構造函數,但是如果基類的構造函數是虛函數的話,派生類的構造函數又會把基類的構造函數覆蓋,所以無法進一步執行而出錯。同時,虛函數通過虛函數表來實現,而指向虛函數表的指針也需要在對象實例化后創建,那么就違背了先實例化后調用的准則。

7.純虛函數是什么?
    純虛函數是在基類中聲明的虛函數,它在基類中沒有定義,但要求任何派生類都要定義自己的實現方法。帶有純虛函數的類為抽象類。析構函數可以是純虛的,但純虛析構函數必須有定義體,因為析構函數的調用是在子類中隱含的。

8.虛函數與純虛函數的區別?
    定義一個函數為虛函數,不代表函數為不被實現的函數。
    定義他為虛函數是為了允許用基類的指針來調用子類的這個函數。
    定義一個函數為純虛函數,才代表函數沒有被實現。
    定義純虛函數是為了實現一個接口,起到一個規范的作用,規范繼承這個類的程序員必須實現這個函數。

9.簡單描述虛繼承與虛基類?
    為了避免多繼承產生的二義性,在這種機制下,不論虛基類在繼承體系中出現了多少次,在派生類中都只包含一份虛基類的成員。

10.簡單描述多態?
    C++ 多態有兩種:靜態多態、動態多態。靜態多態是通過函數重載實現的;動態多態是通過虛函數實現的。

11.C++內存分為哪幾塊?
    棧,在執行函數時,函數內局部變量的存儲單元都可以在棧上創建,函數執行結束時這些存儲單元自動被釋放。棧內存分配運算內置於處理器的指令集中,效率很高,但是分配的內存容量有限。
    堆,就是那些由new分配的內存塊,他們的釋放編譯器不去管,由我們的應用程序去控制,一般一個new就要對應一個delete。如果程序員沒有釋放掉,那么在程序結束后,操作系統會自動回收。
    全局/靜態存儲區,全局變量和靜態變量被分配到同一塊內存中,在以前的C語言中,全局變量又分為初始化的和未初始化的,在C++里面沒有這個區分了,他們共同占用同一塊內存區。
    常量存儲區,這是一塊比較特殊的存儲區,他們里面存放的是常量,不允許修改。

12.簡單介紹內存池?
    內存池是一種內存分配方式。通常我們習慣直接使用new、malloc申請內存,這樣做的缺點在於所申請內存塊的大小不定,當頻繁使用時會造成大量的內存碎片並進而降低性能。內存池則是在真正使用內存之前,預先申請分配一定數量、大小相等(一般情況下)的內存塊留作備用。當有新的內存需求時,就從內存池中分出一部分內存塊,若內存塊不夠再繼續申請新的內存。這樣做的一個顯著優點是,使得內存分配效率得到提升。

13.簡單描述內存泄漏?
    內存泄漏一般是指堆內存的泄漏,也就是程序在運行過程中動態申請的內存空間不再使用后沒有及時釋放,導致那塊內存不能被再次使用。

14.內存中的堆與棧有什么區別?
    堆空間的內存是動態分配的,一般存放對象,並且需要手動釋放內存。棧空間的內存是由系統自動分配,一般存放局部變量,比如對象的地址等值,不需要程序員對這塊內存進行管理,棧是運行時的單位,而堆是存儲的單位。堆中的共享常量和緩存 。棧解決程序的運行問題,即程序如何執行,或者說如何處理數據;堆解決的是數據存儲的問題,即數據怎么放、放在哪兒。

15.說幾個C++11的新特性?
    auto類型推導:讓編譯器通過初值推斷變量的類型(auto定義的變量必須要有初始值),編譯時對變量進行了類型推導,所以不會對程序的運行效率造成不良影響。
    范圍for循環:遍歷給定序列的每個元素並對序列中的每個值執行某種操作。
    lambda函數:用於定義並創建匿名的函數對象,以簡化編程工作。
    Override:override關鍵字保證了派生類中聲明重寫的函數與基類虛函數有相同的簽名,可避免一些拼寫錯誤
    final 關鍵字:final限定某個類不能被繼承或某個虛函數不能被重寫。
    空指針常量nullptr消除NULL的二義性問題。因為c++中NULL就是0,0 既可以表示整型,也可以表示一個空指針(void *)。nullptr有類型,且可以被隱式轉換為指針類型。
    線程支持、智能指針等

16.簡單介紹智能指針?
    智能指針:C++內存管理是一個令人很頭疼的事情,盡管每次寫完new都會寫一個delete,但是如果程序還沒有執行到delete的時候就跳轉了或者函數返回了,那么就會導致內存泄漏,使用智能指針可以很大程度上的避免這個問題,因為智能指針就是一個類,當類的實例超出了作用域的時候,就會自動調用其析構函數,析構函數會自動釋放資源。
    三種智能指針:unique_ptr,shared_ptr,weak_ptr。shared_ptr維護了一個指向control block的指針對象,來記錄引用個數。weak_ptr用於避免shared_ptr相互指向產生的環形結構,造成的內存泄漏。weak_ptr count是弱引用個數;弱引用個數不影響shared count和對象本身,shared count為0時則直接銷毀。
判斷weak_ptr的對象是否失效有三種方法:1.expired():檢查被引用的對象是否已刪除。2.lock()會返回shared指針,判斷該指針是否為空。3.use_count()也可以得到shared引用的個數,但速度較慢。

17.shared_ptr 和 unique_ptr區別?
    unique具有唯一性,對指向的對象值存在唯一的unique_ptr。unique_ptr不可復制,賦值,但是move()可以轉換對象的所有權,局部變量的返回值除外。與shared_ptr相比,若自定義刪除器,需要在聲明處指定刪除器類型,而shared不需要,shared自定義刪除器只需要指定刪除器對象即可,在賦值時,可以隨意賦值,刪除器對象也會被賦值給新的對象。unique的實現中,刪除器對象是作為unique_ptr的一部分,而shared_ptr,刪除器對象保存在control_block中。
不能通過weak_ptr直接訪問對象的方法,要先通過lock()轉換為shared_ptr。

18.內聯函數和宏定義的區別?
    宏定義在預處理的時候進行簡單的字符串替換,而內聯函數在編譯時在每個調用內聯函數的地方將函數展開,這樣不用使內聯函數占用棧空間,提高效率。宏定義沒有類型檢查,但是內聯函數還是具有函數的性質,有參數以及返回值。

19.簡述幾大基本排序?
    冒泡排序,選擇排序,插入排序,歸並排序,快速排序,堆排序。(詳細略)

20.快速排序最好和最壞的時間復雜度?
    最好:O(nlogn) 每次選擇的基准數是序列按大小排完序后最中間的數。最壞:O(n^2)每次選擇的基准數是按大小排完序后兩端的其中之一。

21.快速排序最壞情況如何改進?
    可以選取區間中隨機的一個數作為基准數取代選取第一個元素,也可以選取首元素、末元素以及中間元素的中間大的元素作為基准數。

22.struct與union的區別?
    1).struct可以存儲多個成員變量信息;而union每個成員會共用同一個存儲空間。
    2).系統分配給union的內存size就是size最大的成員所需空間大小,struct在分配空間時,根據成員類型不同,會存在字節對齊情況,具體對齊標准和機器有關,可能是4字節或8字節等對齊方式。
    3).在任何同一時刻,union值存放了一個被先選中的成員,而結構體struct的所有成員都存在。

23.說說什么是內存對齊?字節對齊的規則是什么?
    盡管內存是以字節為單位的,但是大部分處理器並不是以字節來存取數據,一般會以四字節、八字節或更長的單位來取內存。使用內存對齊可以保證每次取內存都是訪問塊內存地址首部以提高存取效率。
    字節對齊規則:
    1)結構體中每個變量首地址的偏移量必須能夠被其有效對齊值 min(變量自身對齊值, 編譯器指定對齊值) 整除。
    2)結構體的自身對齊值為結構體中最寬變量的大小,結構體的大小必須被其有效對齊值 min(結構體的自身對齊值, 編譯器指定對齊值) 整除。

24.空類的sizeof大小是多少?
    空類的sizeof大小為1字節,因為空類同樣可以被實例化,那么為了唯一標識實例地址,會隱含添加一個字節。

25.空類、含有虛函數的類、派生類、虛繼承中的派生類、多重繼承中的派生類等 的sizeof大小?
    對於這個問題可詳細參考圖解C++對象模型https://www.cnblogs.com/QG-whz/p/4909359.html
    這里做簡單回答:含有虛函數的類的實例由於需要有一個指針指向虛表,所以需要額外的4字節(32位機器)存放虛表指針。虛繼承中派生類需要存放一個指向虛基類的指針同樣需要4字節(32位機器)。注意計算時要考慮內存對齊。

26.free()一個指針兩次,會出現什么問題 ?
    free一次后,原來指針所指向的堆中的內容已經被清空了,但指針本身的值並沒有被置為null,還是指向原來它所指向的內存空間,然后你再free一次時,由於堆中的內容已經是無效的東西,所以就會出錯。不過,有的編譯器在free時並沒有清理堆中的內存,有時你對它free兩次也不一定出錯。不過這是一個很大的隱患,在實際寫代碼中千萬要注意避開這點。

27.指針越界一定會出現錯誤嗎 ?
    不一定,越界后如果沒有造成堆棧破壞就不會使程序運行出錯,但是越界會帶來程序結果出錯,可能使指針指向其他本不應該指向的地方。

28.C++四種類型轉換符各自的作用?
    static_case: 1)在基本數據類型之間轉換,如把 int 轉換為 char,這種帶來安全性問題由程序員來保證;2)在有類型指針與 void * 之間轉換;(不能使用 static_cast 在有類型指針內轉換。)3)用於類層次結構中基類和派生類之間指針或引用的轉換。上行轉換(派生類---->基類)是安全的;下行轉換(基類---->派生類)由於沒有動態類型檢查,所以是不安全的。
    dynamic_cast: 用於將一個父類的指針/引用轉化為子類的指針/引用(下行轉換)。基類必須要有虛函數,因為 dynamic_cast 是運行時類型檢查,需要運行時類型信息,而這個信息是存儲在類的虛函數表中。
    const_cast: 常量指針(或引用)與非常量指針(或引用)之間的轉換。
    reinterpret: 用在任意指針(或引用)類型之間的轉換。能夠將整型轉換為指針,也可以把指針轉換為整型或數組。

29.淺拷貝是什么?深拷貝是什么?
    淺拷貝:在擁有指針成員的類中,一個對象利用拷貝構造函數或者賦值函數拷貝或者賦值給另一個對象的時候,直接將這個對象的指針成員賦值給另一個對象的指針成員,將一個指針賦值給另一個指針,就會使兩個指針指向同一個空間,這就產生了淺拷貝。淺拷貝會造成一些問題例如內存泄漏、同一片內存釋放多次、一個指針修改了這塊空間的值那么另一個指針也指向這塊空間就會出錯。
    深拷貝:在拷貝構造函數或賦值函數中不是直接的將指針賦給另外一個對象的指針,而是新開辟一塊內存空間,將被拷貝或賦值的對象的指針成員指向新開辟的內存空間,然后再將數據拷貝過去。

30.簡單介紹布隆過濾器?
    當存在大量數據內存放不下時,我們想知道一個數據是否在這些大量的數據里面的時候,就會使用布隆過濾器,一般用於字符串。當我們要映射一個值到布隆過濾器中時,我們需要使用多個不同的哈希函數生成多個不同的哈希值,並將每個生成的哈希值指向的 bit置為 1。但是可以想到,這樣的方法會導致誤判,誤判是不能解決的,只能緩解。布隆過濾器判斷的結果不存在是准確的,存在是不准確的。

31.hash表解決沖突的方法?
    開放地址法:當關鍵字key的哈希地址p=H(key)出現沖突時,以p為基礎,產生另一個哈希地址p1,如果p1仍然沖突,再以p為基礎,產生另一個哈希地址p2,…,直到找出一個不沖突的哈希地址pi ,將相應元素存入其中。
    鏈地址法:基本思想是將所有哈希地址為 i 的元素構成一個稱為同義詞鏈的單鏈表,並將單鏈表的頭指針存在哈希表的第i個單元中,因而查找、插入和刪除主要在同義詞鏈中進行。鏈地址法適用於經常進行插入和刪除的情況。
    建立公共溢出區:這種方法的基本思想是:將哈希表分為基本表和溢出表兩部分,凡是和基本表發生沖突的元素,一律填入溢出表。
    再哈希法: 再哈希法又叫雙哈希法,有多個不同的Hash函數,當發生沖突時,使用第二個,第三個,….,等哈希函數計算地址,直到無沖突。雖然不易發生聚集,但是增加了計算時間。

32.跳表插入刪除過程?
    插入時對該節點隨機一個層數,當然層數有最大限制,在跳表中從高層往底層進行查找,找到插入位置之后修改插入節點的前后指針即可完成插入,刪除同理。

33.新建一個空類,里面有什么函數?
    無參構造函數,析構函數,拷貝構造函數,重載賦值運算符函數。

34.怎么判斷兩個結構體變量是否相等?
    不能用函數memcmp來判斷兩個結構體是否相等:memcmp函數是逐個字節進行比較的,而struct存在字節對齊,同樣的成員可能比較的結果不一樣。可以通過重載==來判斷相等。

35.可以使用static const成員函數嗎?
    不可以,const修飾成員函數其實修飾的是this指針,代表不可以通過函數來修改對象,但是static修飾的成員函數屬於類,壓根就不會有this指針。

36.volatile關鍵字的作用?
    volatile 關鍵字告訴編譯器該關鍵字修飾的變量是隨時可能發生變化的,每次使用它的時候必須從內存中取出它的值,因而編譯器生成的匯編代碼會重新從它的地址處讀取數據放在左值中。這樣看來,如果該變量是一個寄存器變量或者表示一個端口數據或者是多個線程的共享數據,就容易出錯,所以說volatile 可以保證對特殊地址的穩定訪問。

37.構造函數可以拋出異常嗎?析構函數呢?
    構造函數可以拋出異常。C++標准指明析構函數不能、也不應該拋出異常。如果對象出了異常,現在異常處理模塊為了維護系統對象數據的一致性,避免資源泄漏,有責任釋放這個對象的資源,調用對象的析構函數,可現在假如析構過程又再出現異常,那么請問由誰來保證這個對象的資源釋放呢?而且這新出現的異常又由誰來處理呢?不要忘記前面的一個異常目前都還沒有處理結束,因此這就陷入了一個矛盾之中,或者說無限的遞歸嵌套之中。

38.Float 和double在內存中的存儲方法?
     浮點數在內存中以二進制的科學計數法表示,表達式為N = 2^E * F;其中E為階碼(采用移位存儲),F為尾數。float和double都由符號位、階碼、尾數三部分組成,float存儲時使用4個字節,double存儲時使用8個字節。

39.靜態鏈接與動態鏈接?
    靜態鏈接是在形成可執行程序前,而動態鏈接的進行則是在程序執行時鏈接。
    靜態鏈接浪費空間 ,這是由於多進程情況下,每個進程都要保存靜態鏈接函數的副本。更新困難 ,當鏈接的眾多目標文件中有一個改變后,整個程序都要重新鏈接才能使用新的版本。但是靜態鏈接運行效率高。
    動態鏈接當系統多次使用同一個目標文件時,只需要加載一次即可,節省內存空間。程序升級變得容易,當升級某個共享模塊時,只需要簡單的將舊目標文件替換掉,程序下次運行時,新版目標文件會被自動裝載到內存並鏈接起來,即完成升級。

40.為什么要有lambda表達式?
    用於定義並創建匿名的函數對象,以簡化編程工作。

41.什么是std::move()以及什么時候使用它?
    std::move()是C ++標准庫中用於轉換為右值引用的函數。當需要在其他地方“傳輸”對象的內容時,可以使用move,而無需復制。 使用std :: move,對象也可以在不進行復制(並節省大量時間)的情況下獲取臨時對象的內容。避免不必要的深拷貝。

42.Static的用法?
    1)靜態局部變量:作用域只在函數內部,但是在全局靜態存儲區分配內存,也就是說生存周期隨着程序運行結束而結束。會在第一次被執行的時候初始化,以后的函數調用不再初始化。
    2)全局靜態變量/static修飾的函數:隱藏。該變量/函數不能被其他文件引用。
    3)靜態數據成員:只會被初始化一次,與實例無關,並且只能在類外初始化。存儲在全局靜態區。
    4)靜態成員函數:用於修飾類的成員函數。只能訪問靜態數據成員或靜態成員函數。

43.Const的用法?
    1)const修飾變量:存儲在常量區,不允許被修改。修飾指針變量分為指向常量的指針和指針本身是常量。如果修飾的是類的成員變量那么必須在類中定義的時候初始化或者在構造函數的初始化列表中初始化。
    2)const修飾函數:如果修飾返回值表示返回值不可被修改。如果修飾成員函數表示不可在函數中修改任何成員變量。
    3)const修飾對象:表示這個對象是一個常量,在初始化的時候要對所有成員變量都初始化。共有變量只能讀,並且只能調用const成員函數。

44.如果const成員函數想要改變成員變量怎么辦?
    1)mutable修飾的成員變量可以突破const的限制,在被const修飾的函數里也能被修改。
    2)可在函數內使用const_cast將this指針轉化為class*const類型也就是表示指向的對象可以修改。

45.左值和右值的區別?
    左值是可以放在賦值號左邊可以被賦值的值;左值必須要在內存中有實體;右值當在賦值號右邊取出值賦給其他變量的值;右值可以在內存也可以在CPU寄存器。一個對象被用作右值時,使用的是它的內容(值),被當作左值時,使用的是它的地址。

46.說一說移動語義(move)和完美轉發(forward)?
    Move作用是無論給move傳遞了一個左值引用還是一個右值引用,最終返回的,都是一個右值引用。forward指的是函數模板在向其他函數傳遞自身形參的時候,如果相應的實參是左值,那么它就應該被轉發為左值,如果相應的實參是右值,那么它就應該被轉發為右值。為了保留在其他函數針對轉發而來的參數的左右值屬性進行不同處理(比如參數為左值時實施拷貝語義;參數為右值時實施移動語義)的可能性。講的比較仔細的一篇博客https://www.cnblogs.com/catch/p/3507883.html。就是看得頭有點大。

47.模板是什么?使用模板編程實現快排?
    模板是創建泛型函數或者類的一個工具,可以對類型進行參數化。使用模板的目的就是編寫與類型無關的代碼。利用模板簡單實現快排https://paste.ubuntu.com/p/ZKYrFHwjCr/,和普通的快排幾乎沒什么區別,就是將類型作為參數傳進來之后使用。

48.malloc底層原理?
    參考博客https://www.cnblogs.com/zpcoding/p/10808969.html#_labelTop
    1)當開辟的空間小於128K的時候,執行系統調用brk(),其主要移動指針_edata(地址空間中堆段的末尾地址)。
    2)當開辟的空間大於128K的時候,執行mmap()系統調用函數來在堆和棧中間稱為“文件映射區域”的地方找一塊空間來開辟。

49.C++如何調用C函數,C++和C混合編譯?
    在函數前面添加extern”C”。

50.c++如何判斷內存是否泄露?
    檢測內存泄漏的關鍵原理就是,檢查malloc/new和free/delete是否匹配,一些工具也就是這個原理。要做到這點,就是利用宏或者鈎子,在用戶程序與運行庫之間加了一層,用於記錄內存分配情況。

51.虛繼承的實現原理?
    講得很仔細的博客https://blog.csdn.net/xiejingfa/article/details/48028491。虛繼承之所以可以實現在多重派生子類中只保存一份共有虛基類拷貝,關鍵在於虛基類表指針,該指針指向了一個虛基類表,虛基類表中記錄了虛基類表指針與本類的偏移地址和虛基類表指針到共有基類元素之間的偏移量,這樣就維持了一份基類的拷貝。

52.placement new是什么?
    placement new是operator new的一個重載版本,如果你想在已經分配的內存中創建一個對象,使用new是不行的。也就是說placement new允許你在一個已經分配好的內存中(棧或堆中)構造一個新的對象。它只是調用了構造函數,返回一個指向已經分配好的內存的一個指針,所以對象銷毀的時候不需要調用delete釋放空間,但必須調用析構函數銷毀對象。

53.inline函數優點、缺點?
    優點:1)inline定義的內聯函數,函數代碼被放入符號表中,在使用時進行替換(像宏一樣展開),效率很高。2)類的內聯函數也是函數。編繹器在調用一個內聯函數,首先會檢查參數問題,保證調用正確,像對待真正函數一樣,消除了隱患及局限性。3)inline可以作為類的成員函數,可以使用所在類的保護成員及私有成員。
    缺點:內聯函數以復制為代價,活動產生開銷1)如果函數的代碼較長,使用內聯將消耗過多內存 , 這種情況編譯器可能會自動把它作為非內聯函數處理2)如果函數體內有循環,那么執行函數代碼時間比調用開銷大。

54.explicit作用?
    explicit用來防止由構造函數定義的隱式轉換。隱式轉換:可以用單個實參來調用的構造函數定義了從形參類型到該類類型的一個隱式轉換,也就是當一個函數的參數是一個擁有只具有一個參數的構造函數的類的對象時,可以通過單個實參來進行隱式轉換成該類的對象。

55.new可以用free釋放嗎?
    不可以,雖然語法上不會報錯,但是邏輯上是有問題的,delete會調用析構函數,而free不會調用虛構函數,所以new/delete、malloc/free必須成對使用。

56.new低層實現?
    底層調用malloc函數分配內存,然后調用構造函數。

57.unique_ptr可以拷貝嗎?
    不能,因為拷貝構造函數被禁用了。

58.怎么使一個類不能繼承?
    繼承的時候子類在構造的時候要先執行父類的構造函數,所以只要讓類的構造函數和析構函數都設置成private,編譯器就會告訴我們這個類不能被繼承了。

59.對void*你了解什么?
    void* 是一個特殊的指針,它的意義為無類型指針,他可以被賦值為任意類型的指針,但是僅限當作一個指針使用。它不能直接被 * 訪問地址的內容,因為還不知道具體要讀多少個字節。

60.靜態鏈接、動態鏈接具體做了什么?
    靜態鏈接是以目標文件為單位的,將各個目標文件連接起來形成可執行文件。
    動態鏈接的基本思想是把程序按照模塊拆分成各個相對獨立部分,在程序運行時才將它們鏈接在一起形成一個完整的程序,而不是像靜態鏈接一樣把所有程序模塊都鏈接成一個單獨的可執行文件。

61.編譯期間的錯誤、鏈接期間的錯誤?
    編譯時期:變量使用前沒有聲明、書寫代碼時,括號不匹配、代碼行末尾缺少分號、使用保留關鍵字作為變量名或程序名等。
    鏈接時期:程序中使用某些函數只有聲明,沒有定義、找不到某些系統文件等。

62.什么叫全特化?偏特化呢?
    全特化就是模板中的參數全被指定成了確定的類型。
    偏特化就是模板中的模板參數沒有被全部確定,需要編譯器在編譯的時候確定。

63.一個模板類在不同特化之后,得到的類還是不是同一個類?
    不是同一個類,不論是特化還是泛型只要參數不同就不是同一個類。

64.new一個對象背后發生了什么?
    1)調用operator new,給對象分配內存。
    2)調用對象的構造函數。
    3)返回指針。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM