在此提醒,使得它清楚我們正在談論:
int const a; // illegal
int const a = 42; // definition, internal linkage
extern int const a; // declaration, external linkage
extern int const a = 42; // definition , external linkage
注意,如果沒有const
,上述前兩個聲明是一個具有外部鏈接都 定義。這只是正交,並不是很直觀,但這是現行規則所說的。
與給予一個const外部連接的問題在於,只能有一個 具有外部鏈接的對象的定義,並且與一個 例外,只有定義可以具有一個初始化。這意味着對於具有外部鏈接的const的 ,只能在一個 翻譯單元中看到實際值(如果 const用於常量表達式,則必需的實際值)。這可能是默認情況下給予const
內部鏈接的動機。
當然,這不會導致模板問題的結束,理論上至少 ;下面的頭有未定義的行爲,如果它是 包括在多於一個翻譯單元:
#include <std::vector>
int const fixedValue = 42;
inline void insertFixedValue(std::vector<int>& dest)
{
dest.push_back(fixedValue);
}
的標準說不僅必須內聯函數和模板具有 令牌相同的序列,但是,所有的符號的必須將 綁定到每個翻譯單元中的相同對象,或者存在違反 的一個定義規則。並且由於fixedValue
沒有外部連接,因此每個翻譯單元中都有一個唯一的實例。 (有 異常如果符號指const
對象和有 立即左值到右值轉換。由於 std::vector<int>::push_back
然而通過引用接受其參數, 沒有即時左值到右值的轉換,我們得到了一個未定義 行爲)
和當然,任何人只要有一個模板:
template <int& r> ...
不能實例化它。
內部聯動的原因當然是歷史性的。今天, 編譯器必須能夠支持諸如:
struct X
{
static int const a = 42; // declaration!!!, external linkage
};
和功能的各種重複定義。這將是 比較瑣碎延長,允許在 聲明初始化在命名空間範圍類變量的規則,給 類似:
int const a; // illegal
int const a = 42; // definition, external linkage
extern int const a; // declaration, external linkage
extern int const a = 42; // declaration, external linkage
這將恢復正交性(即使它需要額外的輸入) 。它 也將打破幾乎所有現有的代碼。
另一種方法是治療const
變量定義 完全一樣的功能模板今天對待:你可以有多個 定義,但它們都必須是相同的。這大概會避免 大部分(如果不是全部的話)代碼破壞。
'extern const a; '不是有效的C++,我不認爲。你需要像'extern const' ** int **'a;'你在第一個突出顯示的塊中有錯誤,但是在最後一個錯誤。 – 2014-08-06 19:25:13
@RobertCrovella今天我認爲它甚至不是有效的C(如果它是有效的,那肯定是不好的做法)。我修復了它。 – 2014-08-07 08:23:09