h文件中的静态关键字和内部链接

Ita*_*atz 14 c++ static one-definition-rule linkage

还有一个static问题.我看过以下内容:

我仍然无法理解以下行为:我有一个h文件:

// StaticTest.h
#include <stdio.h>

static int counter = 0;

struct A {
    A () {
        counter++;
        printf("In A's ctor(%d)\n", counter);
    }
    ~A () {
        counter--;
        printf("In A's dtor(%d)\n", counter);
    }
};

static A a;
Run Code Online (Sandbox Code Playgroud)

还有两个cpp文件:

// StaticTest1.cpp
#include "StaticTest.h"

int main () {
 return 0;
}
Run Code Online (Sandbox Code Playgroud)

和:

// StaticTest2.cpp
#include "StaticTest.h"
Run Code Online (Sandbox Code Playgroud)

该计划的输出是:

In A's ctor(1)
In A's ctor(2)
In A's dtor(1)
In A's dtor(0)
Run Code Online (Sandbox Code Playgroud)

现在,A构造函数被调用两次,因为h文件被包含两次,并且因为声明了A实例,所以它具有内部链接并且编译器很高兴.由于它也被声明为静态,它也有内部链接,我希望它的值不会在两个文件中共享---但是程序输出意味着值是共享的,因为它最多可以计数2.astaticcountercpp

任何见解?

编辑:对于在文件hcpp文件中声明静态变量的上下文中被认为是"良好的编程习惯"的任何答案也受到欢迎.

CB *_*ley 11

如果StaticTest.h在差异源文件之间共享,那么您将获得未定义的行为.

如果您在不同的翻译单元中定义类或内联函数,那么它们的定义必须相同(相同的标记序列),并且至关重要的是,任何标识符必须引用相同的实体(除非const具有内部链接的对象),如在定义中另一个翻译单位.

您违反此规则是因为counter具有内部链接,因此在不同的翻译单元中,函数定义中的标识符引用不同的对象.

参考:C++ 03 3.2 [basic.def.odr]/5.

  • @Itamar Katz:是的,你有不止一个名为`counter`的实体(每个都有内部链接),但你违反了对A`,A :: A`和'A ::〜A的定义的ODR `.虽然你的定义包含相同的令牌序列(好),因为`counter`具有内部链接,当你在'A`的定义中使用该标识符时,它指的是每个单独的翻译单元中的不同对象.这意味着"A"的定义在违反ODR的翻译单元中不相同. (3认同)
  • 不,问题来了,因为类的名称和它的成员有外部链接.所以应该有一个也是唯一一个定义类的成员函数.既然如此,哪个柜台应该更新?因此,如果违反ODR,则为UB.但是,在具有内部链接的函数内使用静态命名空间范围变量应该没有问题,也没有UB. (2认同)