正确使用'extern'关键字

pet*_*zik 9 c++ extern

有些来源(书籍,在线资料)解释了extern如下用法:

extern int i;        // declaration - has 'extern'
int i = 1;           // definition  - specified by the absence of 'extern'
Run Code Online (Sandbox Code Playgroud)

并且有些源支持以下语法:

extern int i;        // declaration
extern int i = 1;    // definition  - specified by the equal sign
                     // Both marked with 'extern'
Run Code Online (Sandbox Code Playgroud)

我的问题是-这是一个çC++的区别,或者是一个预ANSIANSI的做法?

现在,更实际的问题:

使用第二种语法,我想创建一个全局对象(从每个编译单元可见).构造函数不带参数,因此无论是括号还是等号都不是必需的.

extern MyClass myobject;
Run Code Online (Sandbox Code Playgroud)

现在,编译器如何区分声明和定义?

编辑:回到学校,我习惯了第一种语法(Borland C).后来我使用了一个编译器(可能是GCC的一些古老版本)拒绝编译没有'extern'的定义.这让我感到困惑.

AnT*_*AnT 11

特别是对于您的示例,C和C++在这里没有区别.适用于这两种语言的基本规则是:如果您的声明包含初始值设定项,那么它就是一个定义.期.它无关紧要,无论是否明确extern.如果它有一个初始化程序,那么它就是一个定义.

这意味着,在命名空间范围都extern int i = 1int i = 1是相等的,即extern在这样的声明是多余的.在C++ extern中,定义在声明的对象时变为非冗余const,因为constC++中的对象默认具有内部链接.例如,使用外部链接extern const int c = 42;定义常量c.

如果声明没有初始化器,那么(并且只有那时)它开始依赖于extern关键字的存在.随着extern它是一个非定义声明.没有extern它是一个定义.(在C中它将是一个暂定的定义,但这与我们背景中的观点不同).

现在,为你的实际问题.要创建全局对象,必须将其声明

extern MyClass myobject;
Run Code Online (Sandbox Code Playgroud)

(通常在头文件中完成),然后在某个翻译单元中将其定义

MyClass myobject;
Run Code Online (Sandbox Code Playgroud)

由于构造函数不带参数,因此这是定义对象的唯一方法.(从C++ 11开始,MyClass myobject{};如果您愿意,也可以使用.)

如果你必须为构造函数提供参数(比如说42),你就可以使用它们

MyClass myobject(42);
Run Code Online (Sandbox Code Playgroud)

extern MyClass myobject(42);
Run Code Online (Sandbox Code Playgroud)

作为定义,因为初始化器的存在确保它确实被解释为定义.