const限定符

名字好难想zzz發表於2024-07-13

2024-7-13
這裡特別是關於多檔案的const在C++ primer中簡單的帶過去了,實際上理解起來需要用到其他像編譯、連結的知識。

特點:

  • 限定變數只讀,因此使用時必須初始化
  • 在多檔案中共享const物件,該變數的定義和宣告都新增extern關鍵字。對於const的實現,實際上是由編譯器在編譯過程中將const變數替換成對應的值,因此在多檔案中,如果共享一個const物件,由於const物件都需要進行初始化,將造成重複定義的問題。
// file_1.cpp 定義並初始化了一個常量,該常量能被其他檔案訪問
extern const int a = GetValue();
// file_1.h 標頭檔案中宣告常量 a
extern const int a; // 此時的 a 與 file_1.cpp 中定義的 a 就是同一個

這個時候自然考慮到只在一個檔案進行定義,在其他檔案進行宣告,思考以下例子1

//a.cpp
#include <iostream>
extern const int i; 
int main() {
	std::cout<<i;
	return 0;
}
//b.cpp
 const int i;

這裡會報錯未定義 i 。

實際上關鍵在於瞭解extern關鍵字的作用:改變const變數的預設連結屬性

//fileA.cpp
extern const int i = 42; // 定義變數i並修改預設連結屬性為全域性可見

//fileB.cpp
extern const int i;  // 宣告這個變數在其他檔案進行了定義

在例子1中,a.cpp中宣告瞭 a 定義在其他檔案中,然而b.cpp中對 i 的定義對a.cpp是不可見的。

但我們還要考慮編譯順序的影響,考慮以下例子2

//1.cpp
extern const int i; //const int i = 1;
const int i = 1; //extern const int i;
int main(){return 0;}
//2.cpp
extern const int i = 2;

只有按1.cpp中註釋的寫法能透過連結

按照編譯的順序檢查檔案,先 extern const int i,這時編譯器會找這句之前是否對 i 進行了初始化,如果沒有,則透過 extern 去檔案外部,在 2.cpp 尋找到了對 i 的定義。這時,i 已經完成了定義。回到1.cpp後,發現了 const int i = 1,這時就會報錯,重複定義:one or more multiply defined symbols found。按註釋順序,當extern const int i 時,已經在這個檔案發現了對 i 的定義,不需要外部連結。
這裡關於編譯的知識還需要補一下