精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

萬(wàn)字長(zhǎng)文超全C++面經(jīng)

開(kāi)發(fā)
為了方便查閱, 補(bǔ)充了可能沒(méi)有面試內(nèi)容的一級(jí)標(biāo)題. 這樣一級(jí)標(biāo)題可以和 C++ Primer 書籍保持一致.

本文經(jīng)自動(dòng)駕駛之心公眾號(hào)授權(quán)轉(zhuǎn)載,轉(zhuǎn)載請(qǐng)聯(lián)系出處。

1. 開(kāi)始

本文目的是整理面試常見(jiàn)的會(huì)問(wèn)到的題目, 具體細(xì)節(jié)的學(xué)習(xí)需要參考 C++ Primer / Effective C++ 系列書籍 / Inside the C++ Object Model 進(jìn)行學(xué)習(xí).

為了方便查閱, 補(bǔ)充了可能沒(méi)有面試內(nèi)容的一級(jí)標(biāo)題. 這樣一級(jí)標(biāo)題可以和 C++ Primer 書籍保持一致.

1.1. C 和 C++ 的區(qū)別

設(shè)計(jì)思想上:

  • C++ 是面向?qū)ο蟮恼Z(yǔ)言, C 是面向過(guò)程的語(yǔ)言

語(yǔ)法上:

  • C++ 具有封裝/繼承/多態(tài)三種特性.
  • C++ 相比 C, 增加了類型安全的功能, 比如強(qiáng)制類型轉(zhuǎn)換.
  • C++ 支持范式編程, 比如模板類/函數(shù)模板等.

2. 變量和基本類型

2.1. 復(fù)合類型

復(fù)合類型(compound type)是指基于其他類型定義的類型. 最常見(jiàn)的是引用和指針.

引用即別名: 引用(reference)為對(duì)象起了另外一個(gè)名字, 引用類型引用(refers to)另外一種類型.

  • 定義引用時(shí), 程序把引用和它的初始值綁定在一起, 而不是將初始值拷貝給引用. 一旦初始化完成, 引用將和它的初始值對(duì)象一直綁定在一起. 因?yàn)闊o(wú)法令引用重新綁定到另外一個(gè)對(duì)象, 因此引用必須初始化.
  • 因?yàn)橐貌皇且粋€(gè)對(duì)象, 所以不能定義引用的引用.

指針(pointer)是指向(point to)另外一種類型的復(fù)合類型.

  • 指針無(wú)需在定義時(shí)賦初值.
  • 指針本身就是一個(gè)對(duì)象, 允許對(duì)指針賦值和拷貝, 而且在指針的生命周期內(nèi)它可以先后指向幾個(gè)不同的對(duì)象.

表 2.1 指針與數(shù)組的區(qū)別

2.2. const限定符

2.2.1. 作用

  • 修飾變量: 表明該變量的值不可以被改變.
  • 修飾指針: 區(qū)分指向常量的指針和常量指針.
  • 修飾引用: 用于形參, 既避免了拷貝, 又避免了函數(shù)對(duì)值的修改.
  • 修飾成員函數(shù): 表示函數(shù)不能修改成員變量(實(shí)際上是修飾this指針)

補(bǔ)充:

  • 對(duì)于局部對(duì)象,常量存放在棧區(qū);
  • 對(duì)于全局對(duì)象, 常量存放在全局/靜態(tài)存儲(chǔ)區(qū);
  • 對(duì)于字面值常量, 常量存放在常量存儲(chǔ)區(qū)(代碼段).

2.2.2. 指向常量的指針 VS 常量指針

參考 C++ Primer 2.4.2 指針和const:

  • 指向常量的指針(pointer to const):
  • 具有只能夠讀取內(nèi)存中數(shù)據(jù), 卻不能夠修改內(nèi)存中數(shù)據(jù)的屬性的指針(底層 const).
  • const int * p;或者int const * p;
  • 常量指針(const pointer): 常量指針是指指針?biāo)赶虻奈恢貌荒芨淖? 即指針本身是一個(gè)常量(頂層 const), 但是指針?biāo)赶虻膬?nèi)容可以改變.
  • 常量指針必須在聲明的同時(shí)對(duì)其初始化, 不允許先聲明一個(gè)指針常量隨后再對(duì)其賦值, 這和聲明一般的常量是一樣的.
  • int * const p = &a;

2.2.3. cosntexpr

  • 常量表達(dá)式(const expression)是指值不會(huì)改變并且在編譯過(guò)程就能得到計(jì)算結(jié)果的表達(dá)式.
  • 一般來(lái)說(shuō), 如果認(rèn)定變量是一個(gè)常量表達(dá)式, 那就把它聲明成constexpr類型.
  • 一個(gè)constexpr指針的初始值必須是nullptr或者0, 或者是存儲(chǔ)于某個(gè)固定地址中的對(duì)象.
  • constexpr函數(shù)是指能用于常量表達(dá)式的函數(shù).
  • 函數(shù)的返回類型及所有的形參的類型都得是字面值類型.
  • 函數(shù)體中必須有且只有一條return語(yǔ)句.

2.2.4. #define VS const

3. 字符串、向量和數(shù)組

4. 表達(dá)式

4.1. 右值

C++的表達(dá)式要不然是右值(rvalue), 要不然是左值(lvalue). 這兩個(gè)名詞是從 C 語(yǔ)言繼承過(guò)來(lái)的, 原本是為了幫助記憶: 左值可以位于賦值語(yǔ)句的左側(cè), 右值則不能.

當(dāng)一個(gè)對(duì)象被用做右值的時(shí)候, 用的是對(duì)象的值(內(nèi)容); 當(dāng)對(duì)象被用做左值的時(shí)候, 用的是對(duì)象的身份(在內(nèi)存中的位置).

4.2. ++i/i++

前置版本++i: 首先將運(yùn)算對(duì)象加 1, 然后將改變后的對(duì)象作為求值結(jié)果.

后置版本i++: 也會(huì)將運(yùn)算對(duì)象加 1, 但是求解結(jié)果是運(yùn)算對(duì)象改變之前的那個(gè)值的副本.

以下摘錄自 More Effective C++ Item 6:

// prefix form(++i): increment and fetch
UPInt&  UPInt::operator++()
{
    *this +=1;        // increment
    return *this;     // fetch
}
// postfix form(i++): fetch and increment
const UPInt UPInt::operator++(int)
{
    const UpInt oldValue = *this; // fetch
    ++(*this);                    // increment
    return oldValue;             // return what was fetched
}

4.3. sizeof運(yùn)算符

4.3.1. 普通變量執(zhí)行sizeof

sizeof運(yùn)算符的結(jié)果部分地依賴于其作用的類型:

  • 對(duì)char或者類型為char的表達(dá)式執(zhí)行sizeof運(yùn)算, 結(jié)果得 1.
  • 對(duì)引用類型執(zhí)行sizeof運(yùn)算得到被引用對(duì)象所占空間的大小.
  • 對(duì)指針執(zhí)行sizeof運(yùn)算得到指針本身所占空間的大小.
  • 對(duì)解引用指針執(zhí)行sizeof運(yùn)算得到指針指向的對(duì)象所占空間的大小.
  • 對(duì)數(shù)組執(zhí)行sizeof運(yùn)算得到整個(gè)數(shù)組所占空間的大小, 等價(jià)于對(duì)數(shù)組中所有元素各執(zhí)行一次sizeof運(yùn)算并將所得結(jié)果求和.
  • 對(duì)string對(duì)象或vector對(duì)象執(zhí)行sizeof運(yùn)算只返回該類型固定部分的大小.

4.3.2. 類執(zhí)行sizeof

class A {};
class B { B(); ~B() {} };
class C { C(); virtual ~C() {} };
class D { D(); ~D() {} int d; };
class E { E(); ~E() {} static int e; };
int main(int argc, char* argv[]) {
    std::cout << sizeof(A) << std::endl; // 輸出結(jié)果為1
    std::cout << sizeof(B) << std::endl; // 輸出結(jié)果為1
    std::cout << sizeof(C) << std::endl; // 輸出結(jié)果為8,實(shí)例中有一個(gè)指向虛函數(shù)表的指針
    std::cout << sizeof(D) << std::endl; // 輸出結(jié)果為4,int占4個(gè)字節(jié)
    std::cout << sizeof(E) << std::endl; // 輸出結(jié)果為1,static不算
    return 0;
}
  • 定義一個(gè)空類型, 里面沒(méi)有成員變量和成員函數(shù), 求sizeof結(jié)果為 1. 空類型的實(shí)例中不包括任何信息, 本來(lái)求sizeof得到0, 但是當(dāng)我們聲明該類型的實(shí)例的時(shí)候, 它必須在內(nèi)存中占有一定的空間, 否則則無(wú)法使用這些實(shí)例, 至于占用多少內(nèi)存, 由編譯器決定, 一般有一個(gè)char類新的內(nèi)存.
  • 如果在該類型中添加一個(gè)構(gòu)造函數(shù)和析構(gòu)函數(shù), 再對(duì)該類型求sizeof結(jié)果仍為 1. 調(diào)用構(gòu)造函數(shù)和析構(gòu)函數(shù)只需要知道函數(shù)的地址即可, 而這些函數(shù)的類型只與類型相關(guān), 而與類型的實(shí)例無(wú)關(guān), 編譯器也不會(huì)因?yàn)檫@兩個(gè)函數(shù)在實(shí)例內(nèi)添加任何額外的信息.
  • 如果把析構(gòu)函數(shù)標(biāo)記為虛函數(shù), 就會(huì)為該類型生成虛函數(shù)表, 并在該類型的每一個(gè)實(shí)例中添加一個(gè)指向虛函數(shù)表的指針. 在 32 位的機(jī)器上, 一個(gè)指針占 4 字節(jié)的空間, 因此求sizeof得到 4; 在 64 位機(jī)器上, 一個(gè)指針占 8 字節(jié)的空間, 因此求sizeof得到 8.

4.4. 顯式轉(zhuǎn)換

  • static_cast: 任何具有明確定義的類型轉(zhuǎn)換, 只要不包含底層const, 都可以使用static_cast.
  • dynamic_cast: 用于(動(dòng)態(tài))多態(tài)類型轉(zhuǎn)換. 只能用于含有虛函數(shù)的類, 用于類層次間的向上向下轉(zhuǎn)化.
  • const_cast: 去除"指向常量的指針"的const性質(zhì).
  • reinterpret_cast: 為運(yùn)算對(duì)象的位模式提供較低層次的重新解釋, 常用于函數(shù)指針的轉(zhuǎn)換.

5. 語(yǔ)句

6. 函數(shù)

6.1. 函數(shù)基礎(chǔ)

6.1.1. 形參和實(shí)參

實(shí)參是形參的初始值.

6.1.2. static

  • 修飾局部變量: 使得被修飾的變量成為靜態(tài)變量, 存儲(chǔ)在靜態(tài)區(qū). 存儲(chǔ)在靜態(tài)區(qū)的數(shù)據(jù)生命周期與程序相同, 在main函數(shù)之前初始化, 在程序退出時(shí)銷毀. 默認(rèn)初始化為 0.
  • 修飾全局變量: 限制了鏈接屬性, 使得全局變量只能在聲明它的源文件中訪問(wèn).
  • 修飾普通函數(shù): 使得函數(shù)只能在聲明它的源文件中訪問(wèn).
  • 修飾類的成員變量和成員函數(shù): 使其只屬于類而不是屬于某個(gè)對(duì)象. 對(duì)多個(gè)對(duì)象來(lái)說(shuō), 靜態(tài)數(shù)據(jù)成員只存儲(chǔ)一處, 供所有對(duì)象共用.
  • 靜態(tài)成員調(diào)用格式<類名>::<靜態(tài)成員>
  • 靜態(tài)成員函數(shù)調(diào)用格式<類名>::<靜態(tài)成員函數(shù)名>(<參數(shù)表>)

6.2. 參數(shù)傳遞

指針參數(shù)傳遞本質(zhì)上是值傳遞, 它所傳遞的是一個(gè)地址值.

一般情況下, 輸入用傳值或者傳const reference. 輸出傳引用(或者指針).

6.3. 內(nèi)聯(lián)函數(shù)

6.3.1. 使用

將函數(shù)指定為內(nèi)聯(lián)函數(shù)(inline), 通常就是將它在每個(gè)調(diào)用點(diǎn)上"內(nèi)聯(lián)地"展開(kāi).

一般來(lái)說(shuō), 內(nèi)聯(lián)機(jī)制用于優(yōu)化規(guī)模較小(Google C++ Style 建議 10 行以下)、流程直接、頻繁調(diào)用的函數(shù).

在類聲明中定義的函數(shù), 除了虛函數(shù)的其他函數(shù)都會(huì)自動(dòng)隱式地當(dāng)成內(nèi)聯(lián)函數(shù).

6.3.2. 編譯器對(duì)inline函數(shù)的處理步驟

  • 將inline函數(shù)體復(fù)制到inline函數(shù)調(diào)用點(diǎn)處;
  • 為所用inline函數(shù)中的局部變量分配內(nèi)存空間;
  • 將inline函數(shù)的的輸入?yún)?shù)和返回值映射到調(diào)用方法的局部變量空間中;
  • 如果inline函數(shù)有多個(gè)返回點(diǎn), 將其轉(zhuǎn)變?yōu)閕nline函數(shù)代碼塊末尾的分支(使用 GOTO).

6.3.3. 優(yōu)缺點(diǎn)

優(yōu)點(diǎn):

  1. 內(nèi)聯(lián)函數(shù)同宏函數(shù)一樣將在被調(diào)用處進(jìn)行代碼展開(kāi), 省去了參數(shù)壓棧、棧幀開(kāi)辟與回收, 結(jié)果返回等, 從而提高程序運(yùn)行速度.
  2. 內(nèi)聯(lián)函數(shù)相比宏函數(shù)來(lái)說(shuō), 在代碼展開(kāi)時(shí), 會(huì)做安全檢查或自動(dòng)類型轉(zhuǎn)換(同普通函數(shù)), 而宏定義則不會(huì).
  3. 在類中聲明同時(shí)定義的成員函數(shù), 自動(dòng)轉(zhuǎn)化為內(nèi)聯(lián)函數(shù), 因此內(nèi)聯(lián)函數(shù)可以訪問(wèn)類的成員變量, 宏定義則不能.
  4. 內(nèi)聯(lián)函數(shù)在運(yùn)行時(shí)可調(diào)試, 而宏定義不可以.

缺點(diǎn):

  1. 代碼膨脹. 內(nèi)聯(lián)是以代碼膨脹(復(fù)制)為代價(jià), 消除函數(shù)調(diào)用帶來(lái)的開(kāi)銷. 如果執(zhí)行函數(shù)體內(nèi)代碼的時(shí)間, 相比于函數(shù)調(diào)用的開(kāi)銷較大, 那么效率的收獲會(huì)很少. 另一方面, 每一處內(nèi)聯(lián)函數(shù)的調(diào)用都要復(fù)制代碼, 將使程序的總代碼量增大, 消耗更多的內(nèi)存空間.
  2. inline函數(shù)無(wú)法隨著函數(shù)庫(kù)升級(jí)而升級(jí). inline函數(shù)的改變需要重新編譯, 不像non-inline可以直接鏈接.
  3. 是否內(nèi)聯(lián), 程序員不可控. 內(nèi)聯(lián)函數(shù)只是對(duì)編譯器的建議, 是否對(duì)函數(shù)內(nèi)聯(lián), 決定權(quán)在于編譯器.

6.4. 返回類型和return語(yǔ)句

調(diào)用一個(gè)返回引用的函數(shù)得到左值, 其他返回類型得到右值.

6.5. 特殊用途語(yǔ)言特性

6.5.1. 調(diào)試幫助

assert是一種預(yù)處理器宏. 使用一個(gè)表達(dá)式作為它的條件:

assert(expr);

首先對(duì)expr求值, 如果表達(dá)式為false. assert輸出信息并終止程序的執(zhí)行. 如果表達(dá)式為true. assert什么也不做.

6.6. 函數(shù)指針

函數(shù)指針指向的是函數(shù)而非對(duì)象. 和其他指針一樣, 函數(shù)指針指向某種特定類型. 函數(shù)的類型由它的返回類新和形參共同決定, 與函數(shù)名無(wú)關(guān).

C 在編譯時(shí), 每一個(gè)函數(shù)都有一個(gè)入口地址, 該入口地址就是函數(shù)指針?biāo)赶虻牡刂?

有了指向函數(shù)的指針變量后,可用該指針變量調(diào)用函數(shù),就如同用指針變量可引用其他類型變量一樣

用途: 調(diào)用函數(shù)和做函數(shù)的參數(shù), 比如回調(diào)函數(shù).

char * fun(char * p)  {…}  // 函數(shù)fun
char * (*pf)(char * p);    // 函數(shù)指針pf
pf = fun;                  // 函數(shù)指針pf指向函數(shù)fun
pf(p);                     // 通過(guò)函數(shù)指針pf調(diào)用函數(shù)fun

7. 類

7.1. 定義抽象數(shù)據(jù)類型

7.1.1. this指針

  • this指針是一個(gè)隱含于每一個(gè)非靜態(tài)成員函數(shù)中的特殊指針. 它指向調(diào)用該成員函數(shù)的那個(gè)對(duì)象.
  • this的目的總是指向"這個(gè)"對(duì)象, 所以this是一個(gè)常量指針, 被隱含地聲明為:ClassName * const this, 這意味著不能給this指針賦值;
  • 在ClassName類的const成員函數(shù)中, this指針的類型為:const ClassName* const, 這說(shuō)明不能對(duì)this指針?biāo)赶驅(qū)ο筮M(jìn)行修改.
  • 當(dāng)對(duì)一個(gè)對(duì)象調(diào)用成員函數(shù)時(shí), 編譯程序先將對(duì)象的地址賦給this指針, 然后調(diào)用成員函數(shù), 每次成員函數(shù)存取數(shù)據(jù)成員時(shí), 都隱式使用this指針.
  • 當(dāng)一個(gè)成員函數(shù)被調(diào)用時(shí), 自動(dòng)向它傳遞一個(gè)隱含的參數(shù), 該參數(shù)是一個(gè)指向這個(gè)成員函數(shù)所在的對(duì)象的指針.
  • this并不是一個(gè)常規(guī)變量, 而是個(gè)右值, 所以不能取得this的地址(不能&this).
  • 在以下場(chǎng)景中, 經(jīng)常需要顯式引用this指針:
  • 為實(shí)現(xiàn)對(duì)象的鏈?zhǔn)揭?
  • 為避免對(duì)同一對(duì)象進(jìn)行賦值操作;
  • 在實(shí)現(xiàn)一些數(shù)據(jù)結(jié)構(gòu)時(shí), 如list.

7.1.2. 拷貝函數(shù)

  • C++深拷貝與淺拷貝
  • 在未定義顯示拷貝構(gòu)造函數(shù)的情況下, 系統(tǒng)會(huì)調(diào)用默認(rèn)的拷貝函數(shù)——即淺拷貝, 它能夠完成成員的一一復(fù)制. 當(dāng)數(shù)據(jù)成員中沒(méi)有指針時(shí), 淺拷貝是可行的; 但當(dāng)數(shù)據(jù)成員中有指針時(shí), 如果采用簡(jiǎn)單的淺拷貝, 則兩類中的兩個(gè)指針將指向同一個(gè)地址, 當(dāng)對(duì)象快結(jié)束時(shí), 會(huì)調(diào)用兩次析構(gòu)函數(shù), 而導(dǎo)致指針懸掛現(xiàn)象, 所以此時(shí)必須采用深拷貝.
  • 深拷貝與淺拷貝的區(qū)別就在于深拷貝會(huì)在堆內(nèi)存中另外申請(qǐng)空間來(lái)儲(chǔ)存數(shù)據(jù), 從而也就解決了指針懸掛的問(wèn)題. 簡(jiǎn)而言之, 當(dāng)數(shù)據(jù)成員中有指針時(shí), 必須要用深拷貝.

7.1.3. 析構(gòu)函數(shù)

(TODO: 整理析構(gòu)函數(shù)的特性)

  • 析構(gòu)順序與構(gòu)造函數(shù)的構(gòu)造順序相反.
  • 當(dāng)對(duì)象結(jié)束生命周期時(shí), 系統(tǒng)會(huì)自動(dòng)執(zhí)行析構(gòu)函數(shù).
  • 析構(gòu)函數(shù)聲明時(shí)在函數(shù)名前加取反符~, 不帶任何參數(shù), 也沒(méi)有返回值.
  • 如果用戶沒(méi)有聲明析構(gòu)函數(shù), 系統(tǒng)會(huì)自動(dòng)生成一個(gè)缺省的析構(gòu)函數(shù).
  • 如果類中有指針, 且在使用的過(guò)程中動(dòng)態(tài)申請(qǐng)了內(nèi)存, 那么需要顯示構(gòu)造析構(gòu)函數(shù), 在銷毀類之前, 釋放掉申請(qǐng)的內(nèi)存空間, 避免內(nèi)存泄漏.

7.2. 訪問(wèn)控制與封裝

7.2.1. public/private/protected

  • 定義在public說(shuō)明符之后的成員在整個(gè)程序內(nèi)可被訪問(wèn), public成員定內(nèi)的接口.
  • 定義在private說(shuō)明符之后的成員可以被類的成員函數(shù)訪問(wèn), 但是不能被使用該類的代碼訪問(wèn), private部分封裝了(即隱藏了)類的實(shí)現(xiàn)細(xì)節(jié).
  • 基類希望它的派生類有權(quán)訪問(wèn)該成員, 同時(shí)禁止其他用戶訪問(wèn). 我們用受保護(hù)的(protected)訪問(wèn)運(yùn)算符說(shuō)明這樣的成員.

7.2.2. struct和class的區(qū)別

  • struct與class定義的唯一區(qū)別就是默認(rèn)的訪問(wèn)權(quán)限(struct默認(rèn)是public, class默認(rèn)是private).
  • 使用習(xí)慣上, 只有少量成員變量的的用struct定義.

7.2.3. 友元

類可以允許其他類或者函數(shù)訪問(wèn)它的非公有成員, 方法是令其他類或者函數(shù)成為它的有元(friend).

7.3. 構(gòu)造函數(shù)再探

7.3.1. 初始化順序

成員變量的初始化順序與它們?cè)陬惗x中的出現(xiàn)順序一致: 構(gòu)造函數(shù)初始值列表中初始值的前后位置關(guān)系不會(huì)影響

7.3.2. explicit

  • 用于類的構(gòu)造函數(shù), 阻止其執(zhí)行隱式類型轉(zhuǎn)換, 但是仍可以被用來(lái)進(jìn)行顯式類型轉(zhuǎn)換.

8. I/O 庫(kù)

9. 順序容器

9.1. 容器庫(kù)概覽

9.1.1. 迭代器

  • 迭代器(Iterator)模式又稱游標(biāo)(Cursor)模式, 用于提供一種方法順序訪問(wèn)一個(gè)聚合對(duì)象中各個(gè)元素, 而又不需暴露該對(duì)象的內(nèi)部表示.
  • 迭代器本質(zhì)上是類模板, 只是表現(xiàn)地像指針.

9.2. 順序容器操作

9.2.1. emplace

當(dāng)調(diào)用push或insert成員函數(shù)時(shí), 我們將元素類型的對(duì)象傳遞給它們, 這些對(duì)象被拷貝到容器中. 而當(dāng)我們調(diào)用一個(gè)emplace成員函數(shù)時(shí), 則是將參數(shù)傳遞給元素類型的構(gòu)造函數(shù). emplace成員使用這些參數(shù)在容器管理的內(nèi)存空間中直接構(gòu)造元素.

9.2.2. resize/reserve

  • resize: 改變?nèi)萜鲀?nèi)含有元素的數(shù)量.
  • reserve: 改變?nèi)萜鞯淖畲笕萘?

9.2.3. 容器操作可能使迭代器失效

在向容器中添加元素后:

  • 如果容器是vector或string, 且存儲(chǔ)空間被重新分配, 則指向容器的迭代器, 指針和引用都會(huì)失效.
  • 對(duì)于deque, 插入到除首尾位置之外的任何位置都會(huì)導(dǎo)致迭代器指針和引用失效.
  • 對(duì)于list, 指向容器的迭代器指針和引用仍然有效.

從容器刪除元素后:

  • 對(duì)于list, 指向容器的迭代器指針和引用仍然有效.
  • 對(duì)于deque, 在首尾之外的任何位置刪除元素, 其他元素的迭代器也會(huì)失效.
  • 對(duì)于vector或string, 被刪元素之前的迭代器仍有效, 尾后迭代器失效.
  • 對(duì)于關(guān)聯(lián)式容器(如std::set / std::map), 插入元素不會(huì)使任何迭代器失效.
  • 對(duì)于無(wú)序關(guān)聯(lián)式容器(如std::unordered_set / std::unordered_map), 插入元素之后如果發(fā)生了 Rehash(新元素的個(gè)數(shù)大于max_load_factor() * bucket_count()), 則所有迭代器將失效.

9.3. vector

//動(dòng)態(tài)申請(qǐng)數(shù)組
const int M = 10;
const int N = 10;

//使用new申請(qǐng)一個(gè)一維數(shù)組.訪問(wèn)p_arr[i].
int* p_arr = new int[N];
//使用new申請(qǐng)一個(gè)二維數(shù)組.訪問(wèn):p_arr[i][j].
int(*p_arr)[N] = new int[M][N];
//一維數(shù)組轉(zhuǎn)化為二維數(shù)組.訪問(wèn):p_arr[i*N+j].
int* p_arr = new int[M*N];
//指向指針的指針(指向一維指針數(shù)組).訪問(wèn)p[i][j]
int** p_arr = new int* [M]
for(int i = 0; i < M; i++)
    p_arr[i] = new int[N];
//回收內(nèi)存
for(int i = 0; i < M; i++)
 delete []p_arr[i];
delete []p_arr;

//使用vector申請(qǐng)一個(gè)一維數(shù)組
vector<int> v_arr(n, 0);
vector<int> v_arr{1,0};
//使用vector申請(qǐng)一個(gè)二維數(shù)組, 如果不初始化, 使用[]會(huì)報(bào)錯(cuò)
vector<vector<int>> v_arr(m, vector<int>(n, 0));
vector<vector<int>> v_arr = {{1,0}};

//一維數(shù)組作為函數(shù)參數(shù)
void function(int* a);
void function(int a[]);
void function(int a[N]);
//二維數(shù)組作為函數(shù)參數(shù),他們合法且等價(jià)
void function(int a[M][N]);
void function(int a[][N]);
void function(int (*a)[N])

9.4. string

string s("hello world")
string s2 = s.substring(0, 5); // s2 = hello
string s3 = s.substring(6);    // s3 = world
string s4 = s.substring(6, 11);// s4 = world
string s5 = s.substring(12);   // 拋出一個(gè)out_of_range異常

isalpha(ch); //判斷一個(gè)字符是否是字母
isalnum(ch); //判斷一個(gè)字符是數(shù)字或字母
tolower(ch); //將字母轉(zhuǎn)化成小寫
toupper(ch); //將字母轉(zhuǎn)化為大寫

string str = to_string(num); //將數(shù)字轉(zhuǎn)換成字符串

9.5. vector對(duì)象是如何增長(zhǎng)的

當(dāng)不得不獲取新的內(nèi)存空間時(shí), vector和string的實(shí)現(xiàn)通常會(huì)分配一個(gè)比新的空間需求更大的內(nèi)存空間. 容器預(yù)留這些空間作為備用, 可以用來(lái)保存更多的新元素. 這樣, 就不需要每次添加新元素都重新分配容器的內(nèi)存空間了.

  • capacity操作告訴我們?nèi)萜髟诓粩U(kuò)張內(nèi)存空間的情況下可以容納多少個(gè)元素. reserve操作允許我們通知容器它應(yīng)該準(zhǔn)備保存多少個(gè)元素.
  • 初始時(shí)刻vector的capacity為 0, 塞入第一個(gè)元素后capacity增加為 1.
  • 不同的編譯器實(shí)現(xiàn)的擴(kuò)容方式不一樣, VS2015 中以 1.5 倍擴(kuò)容, GCC以 2 倍擴(kuò)容.
  • 從空間上分析, 擴(kuò)容因子越大, 意味著預(yù)留空間越大, 浪費(fèi)的空間也越多, 所以從空間考慮, 擴(kuò)容因子因越小越好.
  • 從時(shí)間上分析, 如果預(yù)留空間不足的話, 就需要重新開(kāi)辟一段空間, 把原有的數(shù)據(jù)復(fù)制到新空間, 如果擴(kuò)容因子無(wú)限大的話, 那顯然就不再需要額外開(kāi)辟空間了. 所以時(shí)間角度看, 擴(kuò)容因子越大越好.

9.6. 容器適配器

除了順序容器外, 標(biāo)準(zhǔn)庫(kù)還定義了三個(gè)順序容器適配器: stack、queue和priority_queue.

本質(zhì)上, 一個(gè)適配器是一種機(jī)制, 能使某種事物的行為看起來(lái)像另外一種事物一樣.

默認(rèn)情況下, stack和queue是基于deque實(shí)現(xiàn)的, priority_queue是在vector之上實(shí)現(xiàn)的.

9.6.1. priority_queue

std::priority_queue<int> q1; // 默認(rèn)大根堆
std::priority_queue<int, std::vector<int>, std::greater<int>>
    q2(data.begin(), data.end()); // 小根堆
// 使用lambda表達(dá)式
auto cmp = [](int left, int right) { return (left ^ 1) < (right ^ 1); };
std::priority_queue<int, std::vector<int>, decltype(cmp)> q3(cmp);

10. 泛型算法

10.1. lambda 表達(dá)式

一個(gè) lambda 表達(dá)式表示一個(gè)可調(diào)用的代碼單元. 我們可以將其理解為一個(gè)未命名的內(nèi)聯(lián)函數(shù). 一個(gè) lambda 表達(dá)式具有如下形式:

[capture list](parameter list) -> return type {function body}

其中capture list(捕獲列表)是一個(gè) lambda 所在函數(shù)中定義的局部變量的列表(通常為空); return type, parameter list和function body與任何普通函數(shù)一樣, 分別表示返回類型、參數(shù)列表和函數(shù)體. 但是與普通函數(shù)不同, lambda 必須使用尾置返回來(lái)制定返回類新.

我們可以忽略參數(shù)列表和返回類型, 但必須包含捕獲列表和函數(shù)體:

auto f = [] {return 42};

11. 關(guān)聯(lián)容器

  • map: 關(guān)鍵字-值對(duì); set: 關(guān)鍵字即值.
  • map: 按關(guān)鍵字有序保存元素(底層為紅黑樹(shù)); unordered_map: 無(wú)序集合(底層為哈系表).
  • map: 關(guān)鍵字不可重復(fù)出現(xiàn); multimap: 關(guān)鍵字可重復(fù)出現(xiàn).

12. 動(dòng)態(tài)內(nèi)存

12.1. 智能指針

智能指針的行為類似常規(guī)指針, 重要的區(qū)別在于它負(fù)責(zé)自動(dòng)釋放所指向的對(duì)象.

shared_ptr
  • 允許多個(gè)指針指向同一個(gè)對(duì)象.
  • 我們可以認(rèn)為每個(gè)shared_ptr都有一個(gè)關(guān)聯(lián)的計(jì)數(shù)器, 通常稱其為引用計(jì)數(shù). 一旦一個(gè)shared_ptr的計(jì)數(shù)器變?yōu)?0, 他就會(huì)自動(dòng)釋放自己所管理的對(duì)象.
unique_ptr
  • "獨(dú)占"所指向的對(duì)象.
weak_ptr
  • weak_ptr是一種弱引用, 指向shared_ptr所管理的對(duì)象.
  • 可打破環(huán)狀引用(cycles of references, 兩個(gè)其實(shí)已經(jīng)沒(méi)有被使用的對(duì)象彼此相互指向, 使之看似還在 “被使用” 的狀態(tài))的問(wèn)題.
make_shared
  • make_shared 在動(dòng)態(tài)內(nèi)存中分配一個(gè)對(duì)象并初始化它, 返回指向此對(duì)象的shared_ptr.

13. 拷貝控制

13.1. 對(duì)象移動(dòng)

  • 右值引用: 所謂右值引用就是必須綁定到右值的引用. 我們通過(guò)&&而不是&來(lái)獲得右值引用. 右值引用有一個(gè)重要的性質(zhì): 只能綁定到一個(gè)將要銷毀的對(duì)象.
  • 左值持久, 右值短暫: 左值有持久的狀態(tài), 而右值要么是字面常量, 要么是在表達(dá)式求值過(guò)程中創(chuàng)建的臨時(shí)對(duì)象.
  • 通過(guò)調(diào)用std::move來(lái)獲得綁定到左值上的右值引用.
int &&rr1 = 42;  // 正確: 字面常量是右值
int &&rr2 = rr1; // 錯(cuò)誤: 表達(dá)式rr1是左值
int &&rr3 = std::move(rr1); // ok

14. 重載運(yùn)算與類型轉(zhuǎn)換

15. 面向?qū)ο蟪绦蛟O(shè)計(jì)

15.1. OOP: 概述

面向?qū)ο蟪绦蛟O(shè)計(jì)(object-oriented programming)的核心思想是數(shù)據(jù)抽象(封裝)、繼承和動(dòng)態(tài)綁定(多態(tài)).

  • 通過(guò)數(shù)據(jù)抽象, 我們可以將接口與實(shí)現(xiàn)分離;
  • 使用繼承, 可以定義相似的類型并對(duì)其相似關(guān)系建模;
  • 使用動(dòng)態(tài)綁定, 可以在一定程度上忽略相似類型的區(qū)別, 而以統(tǒng)一的方式使用它們的對(duì)象.

15.2. 定義派生類和基類

15.2.1. 初始化順序

  • 每個(gè)類控制它自己的成員初始化過(guò)程
  • 首先初始化基類的部分, 然后按照聲明的順序依次初始化派生類的成員.

15.2.2. 靜態(tài)多態(tài)/動(dòng)態(tài)多態(tài)

  • 靜態(tài)多態(tài)是通過(guò)重載和模板技術(shù)實(shí)現(xiàn),在編譯的時(shí)候確定.
  • 動(dòng)態(tài)多態(tài)通過(guò)虛函數(shù)和繼承關(guān)系來(lái)實(shí)現(xiàn),執(zhí)行動(dòng)態(tài)綁定, 在運(yùn)行的時(shí)候確定.
  • 重載: 兩個(gè)函數(shù)名相同,但是參數(shù)的個(gè)數(shù)或者類型不同.
  • 重寫: 子類繼承父類,符類中函數(shù)被聲明為虛函數(shù),子類中重新定義了這個(gè)虛函數(shù).

15.3. 虛函數(shù)

  • 虛函數(shù): 基類希望派生類覆蓋的函數(shù), 可以將其定義為虛函數(shù), 這樣每一個(gè)派生類可以各自定義適合自生的版本.
  • 當(dāng)基類定義virtual函數(shù)的時(shí)候, 它希望派生類可以自己定義這個(gè)函數(shù).
  • 如果使用virtual, 程序依據(jù)引用或者指針?biāo)赶驅(qū)ο蟮念愋蛠?lái)選擇方法(method).
  • 如果不使用virtual, 程序依據(jù)引用類型或者指針類型選擇一個(gè)方法(method).
  • 虛函數(shù)表指針: 在有虛函數(shù)的類的對(duì)象最開(kāi)始部分是一個(gè)虛函數(shù)表的指針, 這個(gè)指針指向一個(gè)虛函數(shù)表.
  • 虛函數(shù)表中放了虛函數(shù)的地址, 實(shí)際的虛函數(shù)在代碼段(.text)中.
  • 當(dāng)子類繼承了父類的時(shí)候也會(huì)繼承其虛函數(shù)表, 當(dāng)子類重寫父類中虛函數(shù)時(shí)候, 會(huì)將其繼承到的虛函數(shù)表中的地址替換為重新寫的函數(shù)地址.
  • 使用了虛函數(shù), 會(huì)增加訪問(wèn)內(nèi)存開(kāi)銷, 降低效率.

15.3.1. 虛析構(gòu)函數(shù)

Q: 析構(gòu)函數(shù)為什么是虛函數(shù)?

A: 將可能會(huì)被繼承的基類的析構(gòu)函數(shù)設(shè)置為虛函數(shù), 可以保證當(dāng)我們new一個(gè)派生類, 然后使用基類指針指向該派生類對(duì)象, 基類指針時(shí)可以釋放掉派生類的空間, 防止內(nèi)存泄漏.

Q: 為什么 C++ 默認(rèn)析構(gòu)函數(shù)不是虛函數(shù)?

A: C++默認(rèn)的析構(gòu)函數(shù)不是虛函數(shù)是因?yàn)樘摵瘮?shù)需要額外的虛函數(shù)表和虛表指針, 占用額外的內(nèi)存; 所以只有當(dāng)一個(gè)類會(huì)被用作基類時(shí)才將其設(shè)置為虛函數(shù).

15.4. 抽象基類

  • 純虛函數(shù)是一種特殊的虛函數(shù), 在基類中不能對(duì)虛函數(shù)給出有意義的實(shí)現(xiàn), 而把它聲明為純虛函數(shù), 它的實(shí)現(xiàn)留給該基類的派生類去做. 書寫=0就可以將一個(gè)虛函數(shù)說(shuō)明為純虛函數(shù).
  • 含有(或者未經(jīng)覆蓋直接繼承)純虛函數(shù)的類是抽象基類(abstract base class).

虛函數(shù) VS 純虛函數(shù)

  • 類里如果聲明了虛函數(shù), 這個(gè)函數(shù)是實(shí)現(xiàn)的, 哪怕是空實(shí)現(xiàn), 它的作用就是為了能讓這個(gè)函數(shù)在它的子類里面可以被覆蓋(override), 這樣的話, 編譯器就可以使用后期綁定來(lái)達(dá)到多態(tài)了. 純虛函數(shù)只是一個(gè)接口, 是個(gè)函數(shù)的聲明而已, 它要留到子類里去實(shí)現(xiàn).
  • 虛函數(shù)在子類里面可以不重寫; 但純虛函數(shù)必須在子類實(shí)現(xiàn)才可以實(shí)例化子類.
  • 虛函數(shù)的類用于 “實(shí)作繼承”, 繼承接口的同時(shí)也繼承了父類的實(shí)現(xiàn). 純虛函數(shù)關(guān)注的是接口的統(tǒng)一性, 實(shí)現(xiàn)由子類完成.
  • 帶純虛函數(shù)的類叫抽象類, 這種類不能直接生成對(duì)象, 而只有被繼承, 并重寫其虛函數(shù)后, 才能使用. 抽象類被繼承后, 子類可以繼續(xù)是抽象類, 也可以是普通類.

15.5. 訪問(wèn)控制與繼承

  • 公有繼承保持原始狀態(tài)(沒(méi)有特殊要求一般用公有繼承)
  • 私有繼承基類的所有成員都作為派生類的私有成員
  • 保護(hù)繼承基類的public作為派生類的保護(hù)成員, 其他不變.

16. 模板與泛型編程

17. 標(biāo)準(zhǔn)庫(kù)特殊實(shí)施

18. 用于大型程序的工具

18.1. 多重繼承與虛繼承

  • 虛繼承是解決 C++ 多重繼承問(wèn)題的一種手段, 從不同途徑繼承來(lái)的同一基類, 會(huì)在子類中存在多份拷貝, 即浪費(fèi)存儲(chǔ)空間, 又存在二義性的問(wèn)題.
  • 底層實(shí)現(xiàn)原理與編譯器相關(guān), 一般通過(guò)虛基類指針和虛基類表實(shí)現(xiàn), 每個(gè)虛繼承的子類都有一個(gè)虛基類指針(占用一個(gè)指針的存儲(chǔ)空間, 4 字節(jié))和虛基類表(不占用類對(duì)象的存儲(chǔ)空間)(需要強(qiáng)調(diào)的是, 虛基類依舊會(huì)在子類里面存在拷貝, 只是僅僅最多存在一份而已, 并不是不在子類里面了); 當(dāng)虛繼承的子類被當(dāng)做父類繼承時(shí), 虛基類指針也會(huì)被繼承.
  • 實(shí)際上, vbptr 指的是虛基類表指針(virtual base table pointer), 該指針指向了一個(gè)虛基類表(virtual table), 虛表中記錄了虛基類與本類的偏移地址; 通過(guò)偏移地址, 這樣就找到了虛基類成員, 而虛繼承也不用像普通多繼承那樣維持著公共基類(虛基類)的兩份同樣的拷貝, 節(jié)省了存儲(chǔ)空間.

19. 特殊工具和技術(shù)

19.1. 控制內(nèi)存分配

19.1.1. new & delete

string *sp = new string("a value); // 分配并初始化一個(gè)string對(duì)象
string *arr = new string[10];      // 分配10個(gè)默認(rèn)初始化的string對(duì)象

當(dāng)我們使用一條new表達(dá)式時(shí), 實(shí)際執(zhí)行了三步操作:

  • new表達(dá)式調(diào)用一個(gè)名為operate new(或者operate new[])的標(biāo)準(zhǔn)庫(kù)函數(shù). 該函數(shù)(從自由存儲(chǔ)區(qū)上)分配一塊足夠大的, 原始的, 未命名的內(nèi)存空間(無(wú)需指定內(nèi)存塊的大小)以便存儲(chǔ)特定類型的對(duì)象(或?qū)ο蟮臄?shù)組).
  • 編譯器運(yùn)行相應(yīng)的構(gòu)造函數(shù)以構(gòu)造這些對(duì)象, 并為其傳入初值.
  • 對(duì)象被分配了空間并構(gòu)造完成, 返回一個(gè)指向該對(duì)象的指針.
delete sp;  // 銷毀*sp, 然后釋放sp指向的內(nèi)存空間
delete [] arr; // 銷毀數(shù)組中的元素, 然后釋放對(duì)應(yīng)的內(nèi)存空間

當(dāng)我們使用一條delete表達(dá)式刪除一個(gè)動(dòng)態(tài)分配的對(duì)象時(shí), 實(shí)際執(zhí)行了兩步操作:

  1. 對(duì)sp所指的對(duì)象或者arr所指的數(shù)組中的元素執(zhí)行對(duì)應(yīng)的析構(gòu)函數(shù).
  2. 編譯器調(diào)用名為operate delete(或者operate delete[])的標(biāo)準(zhǔn)庫(kù)函數(shù)釋放內(nèi)存空間.

19.1.2. malloc&free

  • malloc需要顯式的指出內(nèi)存大小: 函數(shù)接受一個(gè)表示待分配字節(jié)數(shù)的size_t.
  • 返回指向分配空間的指針(void*)或者返回 0 以表示分配失敗. (從堆上動(dòng)態(tài)分配內(nèi)存)
  • free函數(shù)接受一個(gè)void*, 它是malloc返回的指針的副本, free將相關(guān)內(nèi)存返回給系統(tǒng). 調(diào)用free(0)沒(méi)有任何意義.
// operate new的一種簡(jiǎn)單實(shí)現(xiàn)
void *operater new(size_t size) {
    if (void *men = malloc(size))
        return mem;
    else
        throw bad_alloc();
}
// opearte delete的一種簡(jiǎn)單實(shí)現(xiàn)
void operator delete(void *mem) noexcept { free(mem); }

19.2. 固有的不可移植特性

19.2.1. volatile

  • 當(dāng)對(duì)象的值可能在程序控制或檢測(cè)之外(操作系統(tǒng)、硬件、其它線程等)被改變時(shí), 應(yīng)該將該對(duì)象聲名為volatile. 關(guān)鍵字volatile告訴編譯器不應(yīng)對(duì)這樣的對(duì)象進(jìn)行優(yōu)化.
  • volatile關(guān)鍵字聲明的變量, 每次訪問(wèn)時(shí)都必須從內(nèi)存中取出值(沒(méi)有被volatile修飾的變量, 可能由于編譯器的優(yōu)化, 從 CPU 寄存器中取值).

19.2.2. extern

  • 在多個(gè)文件之間共享對(duì)象.
  • extern "C"的作用是讓 C++ 編譯器將extern "C"聲明的代碼當(dāng)作 C 語(yǔ)言代碼處理, 可以避免 C++ 因符號(hào)修飾導(dǎo)致代碼不能和 C 語(yǔ)言庫(kù)中的符號(hào)進(jìn)行鏈接的問(wèn)題.

20. 鏈接裝載與庫(kù)

本小節(jié)內(nèi)容大部分摘錄自《程序員的自我修養(yǎng) - 鏈接裝載與庫(kù)》

20.1. .h 和 .cpp 文件的區(qū)別

  • .h文件里面放申明, .cpp文件里面放定義.
  • .cpp文件會(huì)被編譯成實(shí)際的二進(jìn)制代碼, 而.h文件是在被 include 中之后復(fù)制粘貼到 .cpp 文件里.

20.2. 編譯和鏈接

  1. 預(yù)編譯(預(yù)處理): 預(yù)編譯過(guò)程主要處理那些源代碼文件中的以"#"開(kāi)始的預(yù)編譯指令. 比如"#include"、"#define"等. 生成.i或者.ii文件.
  2. 編譯: 把預(yù)處理完的文件進(jìn)行一系列的詞法分析、語(yǔ)法分析、語(yǔ)義分析及優(yōu)化后生產(chǎn)相應(yīng)的匯編代碼文件(.s文件).
  3. 匯編: 將匯編代碼轉(zhuǎn)變成機(jī)器可以執(zhí)行的指令(機(jī)器碼), 生成.o文件.
  4. 鏈接: 鏈接器進(jìn)行地址和空間分配、符號(hào)決議、重定位等步驟, 生成 .out文件.

20.3. 程序的內(nèi)存布局

一般來(lái)講, 應(yīng)用程序使用的內(nèi)存空間里有如下"默認(rèn)"區(qū)域.

  • 棧: 棧用于維護(hù)函數(shù)調(diào)用的上下文. 由操作系統(tǒng)自動(dòng)分配釋放, 一般包含以下幾個(gè)方面:
  • 函數(shù)的返回地址和參數(shù)
  • 臨時(shí)變量: 包括函數(shù)的非靜態(tài)局部變量以及編譯器自動(dòng)生成的其他臨時(shí)變量
  • 保存上下文: 包括函數(shù)調(diào)用前后需要保持不變的寄存器
  • 堆: 堆是用來(lái)容納應(yīng)用程序動(dòng)態(tài)分配的內(nèi)存區(qū)域. 由程序員分配釋放 ,當(dāng)程序使用malloc或者new分配內(nèi)存時(shí), 得到的內(nèi)存來(lái)自堆里.
  • 可執(zhí)行文件映像: 存儲(chǔ)著可執(zhí)行文件在內(nèi)存里的映像, 由裝載器在裝載時(shí)將可執(zhí)行文件的內(nèi)存讀取或映射到這里.
  • .data: 靜態(tài)區(qū), 存放全局變量和局部靜態(tài)變量.
  • .bss: 存放未初始化的全局變量和局部靜態(tài)變量.
  • .text: 代碼區(qū), 存放 C 語(yǔ)言編譯后的機(jī)器代碼, 不可在運(yùn)行期間修改.
  • 保留區(qū): 保留區(qū)并不是一個(gè)單一的內(nèi)存區(qū)域, 而是對(duì)內(nèi)存中受到保護(hù)而禁止訪問(wèn)的內(nèi)存區(qū)域的總稱. 如通常 C 語(yǔ)言將無(wú)效指針賦值為 0(NULL), 因此 0 地址正常情況下不可能有有效的訪問(wèn)數(shù)據(jù).

圖 20.1 Linux 進(jìn)程地址空間布局

20.3.1. 段錯(cuò)誤

Q: 程序出現(xiàn)"段錯(cuò)誤(segment fault)"或者"非法操作, 該內(nèi)存地址不能 read/wirte"的錯(cuò)誤信息, 是什么原因?

A: 這是典型的非法指針解引用造成的錯(cuò)誤. 當(dāng)指針指向一個(gè)不允許讀或?qū)懙膬?nèi)存地址, 而程序卻試圖利用指針來(lái)讀或?qū)懺摰刂返臅r(shí)候, 就會(huì)出現(xiàn)這個(gè)錯(cuò)誤. 可能的段錯(cuò)誤發(fā)生的時(shí)機(jī)如下:

  • 指針沒(méi)有初始化或者初始化為nullptr, 之后沒(méi)有給它一個(gè)合理的值就開(kāi)始使用指針.
  • 使用野指針(指向一個(gè)已刪除的對(duì)象或者未申請(qǐng)?jiān)L問(wèn)受限內(nèi)存區(qū)域的指針).
  • 指向常量的指針試圖修改相關(guān)內(nèi)容.

20.4. 編譯型語(yǔ)言 VS 解釋型語(yǔ)言

  • 有的編程語(yǔ)言要求必須提前將所有源代碼一次性轉(zhuǎn)換成二進(jìn)制指令, 也就是生成一個(gè)可執(zhí)行程序(Windows 下的 .exe), 比如 C 語(yǔ)言、C++、Golang、Pascal(Delphi)、匯編等, 這種編程語(yǔ)言稱為編譯型語(yǔ)言, 使用的轉(zhuǎn)換工具稱為編譯器.
  • 有的編程語(yǔ)言可以一邊執(zhí)行一邊轉(zhuǎn)換, 需要哪些源代碼就轉(zhuǎn)換哪些源代碼, 不會(huì)生成可執(zhí)行程序, 比如 Python、JavaScript、PHP、MATLAB 等, 這種編程語(yǔ)言稱為解釋型語(yǔ)言, 使用的轉(zhuǎn)換工具稱為解釋器.
責(zé)任編輯:張燕妮 來(lái)源: 自動(dòng)駕駛之心
相關(guān)推薦

2024-05-10 12:59:58

PyTorch人工智能

2021-10-18 11:58:56

負(fù)載均衡虛擬機(jī)

2022-09-06 08:02:40

死鎖順序鎖輪詢鎖

2021-01-19 05:49:44

DNS協(xié)議

2022-09-14 09:01:55

shell可視化

2020-07-15 08:57:40

HTTPSTCP協(xié)議

2020-11-16 10:47:14

FreeRTOS應(yīng)用嵌入式

2021-12-10 12:20:06

LinuxCC++

2024-03-07 18:11:39

Golang采集鏈接

2022-07-19 16:03:14

KubernetesLinux

2020-07-09 07:54:35

ThreadPoolE線程池

2022-10-10 08:35:17

kafka工作機(jī)制消息發(fā)送

2019-11-06 10:12:19

B端設(shè)計(jì)流程分析

2024-11-28 08:00:00

2023-06-12 08:49:12

RocketMQ消費(fèi)邏輯

2022-09-08 10:14:29

人臉識(shí)別算法

2024-01-05 08:30:26

自動(dòng)駕駛算法

2021-08-26 05:02:50

分布式設(shè)計(jì)

2022-07-15 16:31:49

Postman測(cè)試

2021-06-04 07:27:24

sourcemap前端技術(shù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

国产乡下妇女做爰毛片| 国内自拍第二页| 欧美美女搞黄| 日本少妇一区二区| 日韩视频免费在线| 国产清纯白嫩初高中在线观看性色| 波多野结依一区| 国产亚洲午夜高清国产拍精品| 成人黄色生活片| 国产成人无码一区二区三区在线| 成人av二区| 欧美xxxxx牲另类人与| 久久精品.com| 国产91在线视频蝌蚪| 26uuu色噜噜精品一区二区| 国产精品视频免费在线| 久久久香蕉视频| 日韩精品中文字幕第1页| 欧美成人乱码一区二区三区| 人妻有码中文字幕| 欧美巨大xxxx做受沙滩| 欧美国产日韩亚洲一区| 国产精品日韩一区二区| 在线观看亚洲国产| 亚洲欧美激情诱惑| 欧美激情国产日韩精品一区18| 人妻熟人中文字幕一区二区| 久久97精品| 制服丝袜一区二区三区| 国产精品久久久久9999小说| 激情在线视频播放| 国产精品不卡在线观看| 欧美精品成人一区二区在线观看| www.热久久| 韩国成人精品a∨在线观看| 日本国产欧美一区二区三区| 国产无精乱码一区二区三区| 一本一道久久a久久精品蜜桃 | 欧美一区二区.| 国产一级免费av| 女同性一区二区三区人了人一| 亚洲视频在线观看网站| 欧美一区二区三区成人精品| 久久久免费毛片| 精品国产在天天线2019| 婷婷激情小说网| 色999久久久精品人人澡69| 色狠狠桃花综合| 成人一区二区三| 国产免费不卡| 91成人免费网站| 国产l精品国产亚洲区久久| 蜜桃在线视频| 精品福利免费观看| 免费视频爱爱太爽了| 性网站在线观看| 又紧又大又爽精品一区二区| 国产免费xxx| 黄色大片在线播放| 亚洲视频一区二区在线| 国产经典久久久| www久久日com| 一区二区三区加勒比av| 成人av在线播放观看| 好久没做在线观看| 午夜精品成人在线视频| 日本www在线播放| 国产高清不卡| 欧美日韩国产另类一区| 制服丝袜中文字幕第一页 | 日韩一级片网址| 日本r级电影在线观看| 亚洲成人影音| 亚洲精品v天堂中文字幕| 国产精品300页| 你懂的一区二区三区| 亚洲色图在线观看| 国产极品视频在线观看| 亚洲精品成人| 久久免费视频这里只有精品| 久久精品国产成人av| 久久久久91| 91久久精品国产91久久| 韩国中文字幕hd久久精品| 91原创在线视频| 色涩成人影视在线播放| a视频在线播放| 亚洲风情在线资源站| 亚洲人成无码www久久久| 亚洲精品一区二区在线播放∴| 欧美成人欧美edvon| 在线观看福利片| 中文精品久久| 欧洲s码亚洲m码精品一区| 真实的国产乱xxxx在线91| 国产精品中文字幕日韩精品| 久久国产精品高清| 精品国产丝袜高跟鞋| 精品久久中文字幕| 中文字幕中文在线| 国产毛片久久久| 日韩在线视频观看| 日本三级网站在线观看| 久久精品国产亚洲a| 国产chinese精品一区二区| 国产小视频免费在线网址| 亚洲欧美国产77777| 国产av无码专区亚洲精品| 国产精品久久久久久久久久久久久久久| 亚洲精品一区二区三区福利 | 蜜桃视频污在线观看| 国产蜜臀av在线一区二区三区| 国产 欧美 日韩 一区| 欧美影视资讯| 亚洲精品国产suv| 久久久久久视频| 日韩有码一区二区三区| 91精品免费| 国产成人天天5g影院在线观看| 亚洲一线二线三线视频| 最新天堂在线视频| 中国av一区| 91精品国产色综合| 国产wwwwwww| 久久免费视频一区| 激情小视频网站| av在线成人| 最近的2019中文字幕免费一页| 久久99精品波多结衣一区| 国产不卡在线视频| 四虎4hu永久免费入口| 成人国产在线| 一区二区国产精品视频| 日本熟女毛茸茸| 91在线视频官网| 人妻少妇精品久久| theporn国产在线精品| 欧美乱妇高清无乱码| 亚洲自拍偷拍另类| 国产精品人妖ts系列视频| 激情五月亚洲色图| 精品黄色一级片| 国产精品久久久999| 可以在线观看的av| 在线国产电影不卡| 国产高清一区二区三区四区| 久久一区欧美| 色播五月综合| 福利一区视频| 久久精品视频一| 国产免费黄色大片| 一区二区三区高清在线| 91超薄肉色丝袜交足高跟凉鞋| 最新国产精品久久久| 99视频在线免费观看| 欧美性video| 亚洲精品一区二区三区福利| 日韩精品在线免费视频| 久久嫩草精品久久久精品一| 成熟老妇女视频| 国产一区二区三区四区| 国产精品网红直播| 国产成人在线视频免费观看| 欧美v亚洲v综合ⅴ国产v| 日韩欧美激情视频| 2020国产精品| 亚洲欧美视频二区| 亚洲国产一区二区三区在线播放 | 国产激情久久久久久熟女老人av| 一区二区三区四区视频精品免费 | 国产精品自拍第一页| 亚洲国产精品精华液2区45| 亚洲精品国产久| 国产一区日韩一区| 久久综合久久综合这里只有精品| 国产综合色区在线观看| 久久久999成人| 内射后入在线观看一区| 色狠狠色狠狠综合| 黄色一级片在线免费观看| 99热这里都是精品| 日韩一区二区三区不卡视频| 欧美色图首页| 日韩av电影免费在线观看| 在线观看亚洲精品福利片| 九九热精品视频国产| 九色在线观看| 欧美一区二区私人影院日本| 久久不卡免费视频| 亚洲欧洲成人精品av97| 国产在线不卡av| 美女视频网站久久| 玩弄中年熟妇正在播放| 青青草91久久久久久久久| 国产91免费视频| 国产欧美自拍| 国内精品视频一区| 日韩在线免费电影| 精品一区精品二区| 国产999久久久| 色8久久人人97超碰香蕉987| 黄色一级视频免费| 国产精品免费av| a视频免费观看| 国产东北露脸精品视频| 九九视频精品在线观看| 尹人成人综合网| 中文字幕精品—区二区日日骚| 色狼人综合干| 91成人伦理在线电影| 91福利精品在线观看| 91极品女神在线| 在线视频国产区| 深夜成人在线观看| 你懂的视频在线免费| 欧美mv日韩mv国产| 国产日韩一级片| 欧美日韩免费观看一区三区| www.国产com| 亚洲成人精品一区| 国产又黄又爽又无遮挡| 国产精品高潮久久久久无| 实拍女处破www免费看| caoporm超碰国产精品| 日批视频在线看| 精品一区二区免费| 超碰在线播放91| 久久天堂成人| 97成人在线观看视频| 亚洲狼人精品一区二区三区| www国产无套内射com| 图片区亚洲欧美小说区| 亚洲综合第一| 久久高清免费| 亚洲三区在线观看| 日韩在线视频精品| 一区二区三区视频| 色综合天天爱| 一区二区三区偷拍| 日韩精品1区| 日韩精彩视频| 欧美精选视频在线观看| 日日夜夜精品网站| 欧洲杯什么时候开赛| 视频在线观看成人| 日产精品一区二区| 宅男av一区二区三区| 99久久婷婷| 人人妻人人澡人人爽精品欧美一区| 色喇叭免费久久综合网| 亚洲一卡二卡| 天天久久综合| 粉嫩av一区二区三区天美传媒| 欧美69视频| 人妻少妇精品久久| 亚洲免费婷婷| 一路向西2在线观看| 裸体一区二区三区| 激情图片中文字幕| 国产成人高清视频| 国产白嫩美女无套久久| 久久综合狠狠综合久久综合88| 亚洲av综合一区二区| 国产欧美日韩在线视频| 国产精品精品软件男同| 亚洲老妇xxxxxx| 国产一级在线观看视频| 欧美性猛交xxxxx水多| 中国老头性行为xxxx| 日韩免费观看高清完整版在线观看| 成人精品在线播放| 亚洲欧美日韩天堂| 欧美激情二区| 久久免费观看视频| 91精品国产经典在线观看| 91久久在线观看| 美腿丝袜亚洲图片| 色综合久久av| 欧美日韩爆操| 成人在线看视频| 国产精品77777| 醉酒壮男gay强迫野外xx| 国产精品色噜噜| 国产亚洲第一页| 在线观看不卡视频| www.五月婷婷| 亚洲视频在线观看网站| 蜜桃传媒在线观看免费进入 | 久久一夜天堂av一区二区三区| 成年人在线免费看片| 一区二区三区欧美日韩| www.国产毛片| 欧美一区日韩一区| 黄色片免费在线| 欧美成人在线网站| 成人动漫一区| 97超碰在线播放| 欧美肉体xxxx裸体137大胆| 国产精品videossex国产高清| 久久性天堂网| 日本不卡视频一区| 国产精品久久久久久久久免费相片| 国产精品二区一区二区aⅴ| 欧美年轻男男videosbes| 亚洲欧洲国产综合| 欧美激情2020午夜免费观看| 国产精品久久久久久久久免费高清 | 久久久精品一区二区三区| 中老年在线免费视频| 99久久无色码| 天天av综合| 国产三级三级看三级| 久久综合久久久久88| 久久精品久久国产| 91精品在线一区二区| 国产九九在线| 欧美与黑人午夜性猛交久久久| 日韩中文一区二区| 小说区视频区图片区| 日韩在线播放一区二区| 新91视频在线观看| 亚洲mv大片欧洲mv大片精品| 国产成人a人亚洲精品无码| 中文国产成人精品久久一| 中文字幕在线直播| 国产原创精品| 激情视频一区二区三区| 日韩精品视频网址| 国产精品成人午夜| 亚洲中文字幕一区二区| 中文字幕在线观看亚洲| 最新日韩一区| 日韩影片在线播放| 日韩精品久久理论片| 色哟哟精品观看| 欧美日韩国产综合视频在线观看中文| 亚洲精品911| 欧美精品精品精品精品免费| 亚洲国产视频二区| 91麻豆天美传媒在线| 国产在线视视频有精品| 免费在线观看黄色小视频| 欧美老女人在线| 黄色精品免费看| 99www免费人成精品| 狠狠色狠狠色综合日日tαg| 女同性αv亚洲女同志| 一个色在线综合| 色综合久久久久久| 91国内免费在线视频| 亚洲精品一级二级三级| 日本黄色三级大片| 国产欧美一区二区精品仙草咪| 中文字幕观看视频| 日韩在线视频观看正片免费网站| 亚洲精品69| 欧美在线观看黄| av中文字幕在线不卡| 国产无套丰满白嫩对白| 亚洲无限av看| 99精品在免费线偷拍| 日本中文不卡| 精品综合免费视频观看| 激情五月少妇a| 日韩不卡在线观看| 日韩中文影院| 国产人妻互换一区二区| 成人国产亚洲欧美成人综合网| 久久久久久久黄色片| 在线观看国产精品淫| 久久免费福利| 国产精品宾馆在线精品酒店| 欧美激情中文字幕| av免费在线不卡| 欧美一区在线直播| 日韩欧美二区| 日本50路肥熟bbw| 日本高清不卡aⅴ免费网站| 免费网站黄在线观看| 国产一区二区三区奇米久涩| 日韩综合在线视频| 69av视频在线| 亚洲人成网站免费播放| 国产精品亚洲四区在线观看| 五月丁香综合缴情六月小说| 国产三级一区二区| www.av在线.com| 国产成人在线亚洲欧美| 国产高清一区二区| 欧美深性狂猛ⅹxxx深喉| 欧美精品在线观看一区二区| а√天堂8资源中文在线| 亚洲欧美精品在线观看| 粉嫩aⅴ一区二区三区四区五区| 精品无码一区二区三区的天堂| 久久久精品在线观看| 国产精品嫩模av在线| 中文字幕视频观看| 欧美三电影在线| 少妇淫片在线影院|