連結期

連結期,又稱linkage,控制著對象的可見性。

它和作用域(scope)的區別是:作用域決定了在同一個編譯單元(包含頭檔案以後的源檔案)中該對象的可見性。而連結期決定了跨多個編譯單元時對象的可見性。

基本介紹

  • 中文名:連結期
  • 外文名:link time
  • 性質:控制著對象的可見性
  • 相關概念:編譯期、運行期
  • 學科:計算機科學
概述,程式在連結期執行的操作,舉例,static關鍵字對對象連結期的影響,

概述

連結期(link time)是指程式設計中,連結器目標檔案連結產生執行檔時的行為。通常包括外部引用對象與函式的定址、不同種類的跨模組檢查(類型檢查、模板實例化之後的合併等)、某些程式最佳化等。
程式設計語言可能會指明一些源程式在連結期必須滿足的要求。如名字的可見性。
有些語言或系統,連結的工作放在了運行期,如晚綁定

程式在連結期執行的操作

源檔案的編譯過程包含兩個主要階段,而它們之間的轉換是自動的。
第一個階段是預處理階段,在正式的編譯階段之前進行。預處理階段將根據已放置在檔案中的預處理指令來修改源檔案的內容。
第二個就是連結程式階段,連結期把所有對象檔案中的機器碼組合在一起,並解析它們之間的交叉引用。它還集成了對象模組所使用的庫函式的代碼。這是連結程式的一種簡化表示,因為這裡假定在可執行模組中,模組之間的所有連結都是靜態建立的。實際上有些連結是動態的,即這些連結是在程式執行時建立的。
連結程式靜態地建立函式之間的連結,即在程式執行之前建立組成程式的源檔案中所包含的函式連結。
動態建立的函式之間的連結(在程式執行過程中建立的連結)將函式編譯並連結起來,創建另一種可執行模組—— 動態程式庫或共享庫。動態程式庫中的函式連結是在程式調用函式時才建立的,在程式調用之前,該連結是不存在的。
動態程式庫有幾個重要的優點:一個主要的優點是動態程式庫中的函式可以在幾個並行執行的程式之間共享,這將節省相同函式占用的記憶體空間。另一個優點是動態程式庫在調用其中的函式之前是不會載入到記憶體中的。也就是說,如果不使用給定動態程式庫中的函式,該動態程式庫就不會占用記憶體空間。

舉例

現在的Java是運行時編譯,和C++的編譯方式完全不同,所有的對象都是動態分配記憶體的,而且Java的優點在於不用delete,記憶體撤銷由虛擬機負責。
在c++中對記憶體的管理分為三種:
(1)從靜態存儲區域分配。記憶體在程式編譯的時候就已經分配好,這塊記憶體在程式的整個運行期間都存在。例如全局變數,static變數。
(2)在棧上創建。在執行函式時,函式內局部變數的存儲單元都可以在棧上創建,函式執行結束時這些存儲單元自動被釋放。棧記憶體分配運算內置於處理器的指令集中,效率很高,但是分配的記憶體容量有限。
(3)從堆上分配,亦稱動態記憶體分配。程式在運行的時候用malloc或new申請任意多少的記憶體,程式設計師自己負責在何時用free或delete釋放記憶體。動態記憶體的生存期由我們決定,使用非常靈活,但問題也最多。

static關鍵字對對象連結期的影響

連結期決定了跨多個編譯單元時對象的可見性。C++03定義的連結期包括external(外部連結期)、internal(內部連結期)、no(無連結期)。
static關鍵字對對象連結期的影響主要反映在全局變數、函式上。
// A.cpp// External linkage by defaultint i = 10;// Internal linkagestatic int j = 10;// B.cppextern int i;extern int j;int main(){int x = i;// Link eror below! Unresolved external symbol "j".// int y = j;}
全局變數默認具有外部連結期,就是全局可見——在其他編譯單元(這裡是B.cpp)中可見。加上static之後就變成了內部連結期,所以在其他檔案中無妨訪問,連結器報錯。
函式一樣的。加了static的函式只有本編譯單元可以調用。
static還可以使名字具有外部連結期:
// namespace scope class// MyClass.hclass MyClass{public:// No linkageint m_i;// External linkage!static int m_j;};// MyClass.cpp#include "MyClass.h"int MyClass::m_j = 10;// Another.cpp#include "MyClass.h"int main(){MyClass::m_j = 20;// Compile error below!// m_i = 1;// MyClass::m_i = 1;}
這裡,普通的成員變數是沒有任何連結期的,因為在它的作用域(class scope)以外無法通過名字m_i去直接訪問它。但靜態成員變數擁有外部連結期,所以可以直接在其他編譯單元中訪問,當然前提是加上類名限定(::)。
成員函式無論加不加static,都具有外部連結期。

相關詞條

熱門詞條

聯絡我們