extern关键字真的有必要吗?

时间:2010-05-15 13:09:26

标签: c++ extern

...
#include "test1.h"

int main(..)
{
    count << aaa <<endl;
}

aaatest1.h中定义,我没有使用extern关键字,但仍可以引用aaa

所以我怀疑extern真的有必要吗?

5 个答案:

答案 0 :(得分:12)

extern有其用途。但它主要涉及不满意的“全球变量”。 extern背后的主要思想是用外部联系声明事物。因此,它与static相反。但在许多情况下,外部链接是默认链接,因此在这些情况下您不需要externextern的另一个用途是:它可以将定义转换为声明。例子:

extern int i;  // Declaration of i with external linkage
               // (only tells the compiler about the existence of i)

int i;         // Definition of i with external linkage
               // (actually reserves memory, should not be in a header file)

const int f = 3; // Definition of f with internal linkage (due to const)
                 // (This applies to C++ only, not C. In C f would have
                 // external linkage.) In C++ it's perfectly fine to put
                 // somethibng like this into a header file.

extern const int g; // Declaration of g with external linkage
                    // could be placed into a header file

extern const int g = 3; // Definition of g with external linkage
                        // Not supposed to be in a header file

static int t; // Definition of t with internal linkage.
              // may appear anywhere. Every translation unit that
              // has a line like this has its very own t object.
你知道,它相当复杂。有两个正交的概念:联系(外部与内部)以及声明与定义的关系。 extern关键字可以影响两者。关于联系,它与static相反。但是static的含义也是重载的 - 并且 - 取决于上下文 - 是否控制链接。它的另一个作用是控制对象的生命周期(“静态生命周期”)。但是在全球范围内,所有变量都已经具有静态生命周期,并且有些人认为回收关键字以控制链接是个好主意(这只是猜测)。

Linkage基本上是在“命名空间范围”声明/定义的对象或函数的属性。如果它具有内部链接,则不能通过其他翻译单元的名称直接访问它。如果它具有外部链接,则所有翻译单元中只应有一个定义(有例外,请参阅单定义规则)。

答案 1 :(得分:7)

我发现组织数据的最佳方法是遵循两个简单的规则:

  • 仅在头文件中声明内容。
  • 用C(或cpp定义),但为了简单起见,我将在这里使用C语言。

通过声明,我的意思是通知编译器存在的东西,但不为它们分配存储空间。其中包括typedefstructextern等等。

通过定义,我通常意味着“为{分配空间”,如int等等。

如果你有一行:

int aaa;

在头文件中,每个编译单元(基本上定义为编译器的输入流 - C文件及其带有#include的所有内容,递归)将得到它自己的副本。如果将两个具有相同符号定义的目标文件链接在一起(除了在某些有限的情况下,如const),这将导致问题。

更好的方法是在你的一个C文件中定义aaa变量,然后放入:

extern int aaa;

在你的头文件中。

请注意,如果您的头文件仅包含在一个C文件中,则这不是问题。但是,在这种情况下,我可能甚至没有头文件。在我看来,头文件仅用于在编译单元之间共享内容。

答案 2 :(得分:5)

如果你的test1.h有aaa的定义并且你想将头文件包含到多个翻译单元中,你将遇到多个定义错误,除非aaa是常量。 最好在cpp文件中定义aaa,并在头文件中添加extern定义,可以作为标题添加到其他文件中。

在头文件中具有变量和常量的Thumb规则

 extern int a ;//Data declarations
 const float pi = 3.141593 ;//Constant definitions

由于常量在c ++中具有内部链接,因此在翻译单元中定义的任何常量对于其他翻译单元是不可见的,但对于变量而言它们不具有外部链接,即,它们对于其他翻译单元是可见的。将变量的定义放在标题中,在其他翻译单元中共享将导致变量的多个定义,从而导致多个定义错误。

答案 3 :(得分:3)

在这种情况下,extern不是必需的。当符号在另一个编译单元中声明时,需要使用Extern。

使用#include预处理指令时,将复制包含的文件来代替该指令。在这种情况下,您不需要extern,因为编译器已经知道aaa

答案 4 :(得分:1)

如果aaa没有在另一个编译单元中定义,则不需要extern,否则就行了。