我对以下变量的联系有一些疑问。通过 C++03 的 7.1.1/7 示例和编译器(Comeau、Clang 和 GCC)的实验,我得出以下链接类型:
首先是
static
,然后是extern
static int a; // (a) extern int a; // (b) valid, 'a' still internal
根据第 3.5 节,我很清楚:(a) 暗示内部联系。并且 (b) 也意味着内部链接,因为名称“a”被声明为静态的(由 (a))。
首先是
extern
,然后是static
extern int b; // (c) static int b; // (d) invalid!
首先,(c) 表示外部链接。但是(d)暗示了内部链接,因为名称“b”被(d)声明为静态的。根据 7.1.1/7,这是无效的,因为隐含的链接不一致。
首先是
const
,然后是extern
const double pi1 = 3.14; // (e) extern const double pi1; // (f) valid and 'pi1' is internal
首先,(e) 隐含内部链接,因为它是常量,既没有声明为显式外部链接,也没有先前隐含外部链接。并且 (f) 应该暗示外部链接并且是一个错误,因为它显式声明了名称 extern,但编译器将其保留在内部! 为什么会这样? 这是我的问题。
首先是
extern
,然后是const
extern const double pi2; // (g) const double pi2 = 3.14; // (h) valid and 'pi2' is external
现在,(g) 意味着外部链接,因为我们明确声明了 extern。并且 (h) 也暗示外部链接,因为 (g) 显式声明为 extern。
我已经通过以下模板实验找到了 3 和 4 的链接(第二个参数需要有外部链接)
template<typename T, T&> struct ensure { };
ensure<const double, pi1> e1; // failed
ensure<const double, pi2> e2; // succeeded
总结:与Charles Bailey的讨论结果非常有成果,表明 3.5/3
有两种可能的解释,其中重要的要点是
A name having namespace scope (3.3.5) has internal linkage if it is the name of
- an object or reference that is explicitly declared const and neither explicitly declared extern nor previously declared to have external linkage;
如果我们看点(f)
,那么两种解释会得出不同的结论,如下所示
第一种解释指出
pi1
被声明为const
但也被声明为extern
。因此,该变量具有外部 链接。第二种解释将两次出现的“已声明”解释为指代同一声明。这样,就意味着它被声明为
const
,而不是extern const
。我们注意到(e)
被声明为const
而不是extern const
,因此我们给pi1
内部链接。
现在什么解释是正确的?我无法从该措辞中确定,但编译器似乎以第二种方式解释这一点。特别是,如果我们采用第一种解释,那么 3.5/3
中最后引用的部分将是多余的,因为没有有效的场景可以将名称声明为 const
并且之前使用外部链接声明但没有明确的 extern
。
最佳答案
const double pi1 = 3.14; // (e)
extern const double pi1; // (f) valid and 'pi1' is internal
我的解释如下。在考虑名称的链接时,我们会考虑先前的声明以及在解析中此时正在解释的声明。这就是为什么 static int a; extern int a;
可以,但是 extern int b; static int b;
不是。
在遇到第一个声明时,我们注意到 pi1
被显式声明为 const
但既没有显式声明 extern
也没有先前声明为具有外部链接。这与 3.5/2 的选项之一匹配,因此 pi1
具有内部链接。
在遇到第二个声明时,我们要求 pi1
显式声明 const
但既未显式声明 extern
也未显式声明 [ ...等等...]。我认为这是因为它是在 (e) 点如此宣布的。当然,并不是所有地方都这样声明,但是当我们考虑 extern int a; 时,
声明,即使它没有在任何地方声明为 a
是声明为 static
的对象的名称; static
。对我来说,这意味着声明 (f) 并不意味着与声明 (e) 不同的联系。
关于c++ - 各种常量/静态变量的链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3538807/