头文件中的`static`,`extern`,`const`

Alc*_*ott 8 c++

//a.h

extern int x1;
static int x2;
int x3;
static const int x4;

class A {
    public:
        static const int x5 = 10;
};
Run Code Online (Sandbox Code Playgroud)

a.h将包含多个.cpp文件,我的问题是:

1. x1只是一个宣言,不是吗?所以它的定义应该在其中一个.cpp文件中完成,对吧?

2. x2是一个定义,对吧?我曾经认为这static int也是一个宣言extern int,但我错了.x2只会在a.h

3. x3如果a.h包含在多个.cpp文件中,将被多次定义,因此x3会导致编译错误,对吗?

4. x4是一个定义吧?

x5是A级的声明,是的.但那怎么样x4

Dav*_*eas 10

1.x1只是一个声明,不是吗?所以它的定义应该在其中一个.cpp文件中完成,对吧?

正确

2.x2是一个定义,对吗?我以前认为static int也是一个类似于extern int的声明,但我错了.x2只会在啊?

x2每个包含标题的翻译单元都有不同的名称.

如果多个.cpp文件中包含啊,则将多次定义3.x3,因此x3将导致编译错误,对吧?

更确切地说,它将导致链接器错误.编译器处理每个转换单元,链接器将它们绑定在一起并检测符号是多次定义的.

4.x4是一个定义,对吗?

是的,这是一个定义,但是x2每个翻译单元都有它自己的x4(static因为它是因为它const意味着内部联系)

5.在A级,x5是声明,是的.但是x4怎么样?

是的,x5只是一个声明(初始化).可能会出现混淆,因为关键字static在不同的上下文中被重用以表示不同的事物.在x5它中意味着类的属性,而在x4其中意味着内部链接

最后一个案例很特别.它是唯一的声明(IIRC)声明可以有一个值,原因是它允许编译器在包含该标头的所有转换单元中使用常量的值作为编译时常量.如果必须为定义提供值,则只有一个翻译单元可以访问该值.该静态成员的定义是:

const int A::x5; // no initialization here
Run Code Online (Sandbox Code Playgroud)

如果该成员使用过多,您必须提供一个.现在的事实是,在大多数情况下,常量不会被使用,因为编译器将在使用表达式时替换该值A::x5.仅当成员用作左值时,才需要定义,例如:

void f( const int & ) {}
int main() {
   f( A::x5 );
}
Run Code Online (Sandbox Code Playgroud)

由于参数f是一个参考,使用A::x5需要一个左值(注意,常量性和左值/右值岬几乎正交),并且需要的构件的在一个单一的翻译单元程序中的定义.