C++面試題整理:1.聲明與定義的區別,內部鏈接與外部鏈接,靜態鏈接與動態鏈接

引言

從源碼到可執行程序,經過了編譯、鏈接這兩個過程

  • 編譯:將用戶的源碼編譯成若干目標模塊;展開來講編譯分爲三步編譯預處理(處理一些#定義的命令或語句)、編譯(語法語義分析)、彙編(彙編指令翻譯成機器指令)
  • 鏈接:將若干目標模塊和所需的庫函數鏈接在一起,生成可執行程序

二者的區別:

  • 編譯過程,檢查程序的語法以及函數、變量是否聲明,如果函數未聲明,編譯器會給出警告,但是會生成目標文件
  • 鏈接過程,在目標文件中找尋函數的實現,如果未找到就會報鏈接錯誤碼

1 聲明 與 定義

1.1聲明

將一個名稱引入程序。

1.聲明一個函數:void fun(int a, int b);
2.聲明一個變量:extern int a;
3.聲明一個類:class A;
4.聲明一個類的靜態成員變量:class A{…;static int a;…}
5.聲明類型的別名:typedef int INT;

1.2定義

提供了一個實體在程序中的唯一描述。

1.定義一個類的靜態成員變量:int A::a = 0;
2.定義一個類的(非內聯)成員函數:int A::fun(){return a;}

1.3聲明和定義同時存在

大多數情況下聲明和定義是同時存在的

1.int a;
2.extern int a = 0;

1.4 聲明和定義的區別

在一個給定的作用域內,聲明可以有多次,定義只能有一次。但是類中的函數和靜態成員變量只能聲明一次

2 內部鏈接與外部鏈接

2.1編譯單元

當一個c或者cpp程序在編譯時,會遞歸其頭文件,形成一個含有必要信息的源文件,這個源文件就是一個編譯單元。

2.2內部鏈接

如果一個名稱對於它的編譯單元而言是局部的,不與其他編譯單元相同的名稱衝突,那麼這個名稱具有內部鏈接。
下面的名稱是內部鏈接:

1.所有的聲明
2.命名空間中的靜態自由函數(自由函數是指該函數不是類的成員函數,也不是友元函數)、靜態友元函數、靜態變量的定義
3.枚舉定義
4.內聯函數的定義
5.類的定義
6.命名空間中const常量定義
7.union定義

2.3 外部鏈接

在一個多文件程序中,如果一個名稱在鏈接時可以與其他編譯單元交互,那麼這個名稱就有外部鏈接。
外部鏈接的名稱:

1.類的非內聯函數,包括類的成員函數和靜態成員函數
2.類的靜態成員變量定義。(一定要和聲明區分開,聲明都是內部鏈接)
3.命名空間中的非靜態自由函數、非靜態友元函數、非靜態變量

2.4 總結

1.inline函數總有內部鏈接,不論這個函數是什麼函數,在類中的函數也是如此,所以inline函數最好放在頭文件中,每一個包含頭文件的函數都能夠找到inline函數
2.類定義總有內部鏈接,而非inline類成員函數總有外部鏈接,不論這個成員函數是靜態、虛擬還是一般成員函數,類的靜態數據成員定義總有外部鏈接
3.命名空間中的靜態自由函數,靜態友元函數,靜態變量,const常量定義都有內部鏈接
4.聲明、enum定義、union定義有內部鏈接

3 靜態鏈接 和 動態鏈接

二者的區別在於鏈接的時機不一樣,

  • 靜態鏈接:在形成可執行程序之前
  • 動態鏈接:在程序執行的過程中

3.1 靜態鏈接

將需要調用的函數或者過程鏈接到可執行文件中,成爲可執行程序的一部分,也就是說函數和過程的代碼就在exe文件中,該文件包含了運行中的全部代碼。

優缺點:

  • 浪費空間,因爲每個可執行程序中都有一份其所需目標文件的拷貝,如果多個可執行程序對同一個目標文件有依賴,那該目標文件在內存中就有多個副本
  • 更新困難,如果庫函數的代碼修改了,就需要重新編譯鏈接形成可執行程序
  • 運行速度快,因爲可執行程序中已經具備了程序運行需要的所有東西

3.2 動態鏈接

動態鏈接就是爲了解決靜態鏈接存在浪費空間、更新困難的弊端而出現的。
動態鏈接是將程序按照模塊拆分成相對獨立的部分,在程序運行時,纔將他們鏈接在一起形成完整的程序

優缺點:

  • 同一個目標文件在內存中只有一份
  • 更新方便,只需將原來的目標文件替換即可,無需將所有的程序重新鏈接
  • 運行速度會降低,因爲在運行可執行程序的過程中需要進行鏈接

3.4 如何選擇

如果系統中有多個應用程序使用這個庫,就把它編譯成動態庫,這樣在啓動的時候加載比較慢,但是多任務的時候會節省內存;
如果系統中只有一到兩個應用程序使用該庫,並且使用的API比較少,就編譯成靜態庫,這樣應用程序可能會比較大,但是啓動速度快。

參考:
https://blog.51cto.com/zhanglianpin/1675069

https://blog.csdn.net/kang___xi/article/details/80210717?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章