在未命名的命名空间内使用外部链接初始化变量

时间:2014-07-16 02:20:43

标签: c++ c++11

我想提供'x'的定义。我尝试使用“extern int x = 42”。但是,g ++抱怨'x'同时包含extern和初始化器。我试图找到不允许这样做的c ++ 11规范的相关部分,但我找不到任何这样的子句。这个规格确实不允许这样做吗?如果是,请引用相关部分。

namespace {
    int f() { 
        extern int x;
        return x;
    }
}

2 个答案:

答案 0 :(得分:3)

通过提供初始化程序,您可以将声明转换为具有外部链接的定义

来自§3.1/ 2 [basic.def]

  

声明是一个定义,除非声明一个函数而没有指定函数的主体(8.4),它包含extern说明符(7.1.1)或连接规范(7.5)既不是初始化程序 也不是函数体...

但是外部链接的变量不能在函数内定义,只能在命名空间范围内定义,这就是gcc拒绝你的代码的原因。因此,请在命名空间范围内提供定义。

namespace {
    extern int x = 0;
    int f() { 
        // no need for extern declaration here, name lookup will find x
        return x;
    }
}

这样做会有效,但是给一个未命名的命名空间中定义的名称提供外部链接肯定是很奇怪的,如果没有用的话。


请注意,gcc仍然会对上面的代码发出警告

  

警告:'x'已初始化并声明为'extern'

然而,从gcc bug report关于警告:

  

这是一种编码风格警告 - 代码有效,但非常有用   因为“extern”一般预期意味着C的单一性   声明没有提供对象的定义。

答案 1 :(得分:2)

3.5 / 6

  

块作用域中声明的函数的名称和块作用域extern声明声明的变量的名称具有链接。如果存在具有相同名称和类型的链接的实体的可见声明,忽略在最内部封闭命名空间范围之外声明的实体,则块范围声明声明该实体并接收先前声明的链接。如果存在多个这样的匹配实体,则该程序是不正确的。否则,如果未找到匹配的实体,则块范围实体将接收外部链接。

8.5 / 5

  

具有初始值设定项的外部或内部链接的块范围变量的声明格式不正确。

正如@Praetorian所指出的,您可以将变量定义移到函数定义之外。或者,如果您实际上不需要在该功能之外的任何位置使用名称x,请将extern更改为staticx将没有链接。< / p>