全局变量在头文件中声明为static时没有链接器错误

时间:2011-07-17 16:16:24

标签: c++ linker static-variables

  

可能重复:
  Static variables in C++

// x.h
int i = 3;

// x1.cpp
#include"x.h"
//...

// x2.cpp
#include"x.h"
//...

上面的代码会给链接器错误。但是,如果我宣布,

//x.h
static int i = 3;

它不会在gcc中给出链接器错误,即使我们有相同的#include!我们是否为每个static int i;文件创建了不同的.cpp?它会导致任何无声链接错误(由于同名)吗?

6 个答案:

答案 0 :(得分:4)

编译C代码时,它一次只能是一个“翻译单元”。早期,#include被扩展为引用文件的文本。所以你在静态情况下得到的东西相当于x1.cpp说static int i = 3;和x2.cpp做同样的事情。在这种情况下,static大致意味着“不要与其他翻译单位分享。”

所以是的,当你使用static时,你正在制作两个不同的i变量,它们彼此无关。这不会导致链接错误。

答案 1 :(得分:4)

int x;是实体x的定义。 C ++的One Definition Rule表示,任何使用的变量都应该在程序中只定义一次。因此错误。

staticx有内部联系。也就是说,one.cpptwo.cpp中出现的x是两个不同的不相关实体。

C ++标准说在这种情况下使用静态是不推荐使用的(根据Steve的评论,在C ++ 0x中它是不推荐的)。匿名命名空间提供了一个更好的选择。

namespace
{
   int x;
}

另请注意,与C不同,在C ++中,标量类型的const变量也具有内部链接。那是

const int x = 7; // won't give you an error if included in different source files.

HTH

答案 2 :(得分:3)

  

我们是否正在创建不同的静态int i;对于每个.cpp文件?

  

是否会导致任何无声链接错误(由于同名)?

没有。由于静态,它们有不同的名称。

如果这不是您想要的行为,则需要在头文件中使用extern,并将变量分配到一个翻译单元(.cpp文件)

答案 3 :(得分:2)

static创建一个仅在单元内可见的全局变量。

如果要在ecompilation单元以上使用变量,请在标题中使用extern,并在没有extern的情况下在implmenetation中声明它。

答案 4 :(得分:0)

在第一个代码示例中出现链接器错误,因为i是在两个编译单元中定义和导出的。在第二种情况下,我是静态的,因此没有导出符号,因为静态变量仅在当前编译单元中可见,并且不会导出到链接器。在这种情况下,您有两个独立的变量,都称为i。

答案 5 :(得分:0)

如上所述,代码看起来像多个.cpp文件正在访问i,而实际上,每个.cpp文件都有自己的副本。这可能会导致误解和错误。

如果您希望只有i的一个副本,首选的习惯用法是将其包装在x.h的访问者函数中:

int& GetI() {
  static int i = 3;  // this initialization only happens once.
  return i;
}

如果您执行希望为每个.cpp文件单独复制i,则更明确的表达方式是在每个.cpp文件中单独声明i

namespace {
  int i;
}

为了安全起见,将其置于匿名命名空间中,使其无法从其他.cpp文件访问。