头文件中的“静态”、“外部”、“常量”
`static`, `extern`, `const` in header file
//a.h
extern int x1;
static int x2;
int x3;
static const int x4;
class A {
public:
static const int x5 = 10;
};
a.h
将被多个.cpp
文件包含,我的问题是:
1. x1
只是一个宣言,不是吗?所以它的定义应该在其中一个.cpp
文件中完成,对吧?
2. x2
是一个定义,对吧?我曾经认为static int
和extern int
一样也是一个宣言,但我错了。 x2
只会在a.h
中可见?
3. 如果a.h
包含在多个.cpp
文件中,x3
将被多次定义,因此x3
会导致编译错误,对吗?
4. x4
是一个定义,对吧?
5.在A类中,x5
是一个声明,是的。但是x4
呢?
1.x1只是一个声明,不是吗?所以它的定义应该在其中一个.cpp文件中完成,对吧?
正确
2.x2是一个定义,对吧?我曾经认为静态 int 也是一个声明,就像 extern int 一样,但我错了。X2 只会在 A.H 中可见?
包含标题的每个翻译单元中将提供不同的x2
。
如果 a.h 包含在多个.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
如果成员是使用 odr 的,则必须提供一个。现在的事实是,在大多数情况下,常量不会被 odr 使用,因为编译器会在使用表达式 A::x5
时替换该值。仅当成员用作左值时,您才需要定义,例如:
void f( const int & ) {}
int main() {
f( A::x5 );
}
由于 f
的参数是引用,因此使用 A::x5
需要一个左值(注意,常量和左值/右值几乎是正交的(,这需要在程序中的单个翻译单元中定义成员。
-
正确
-
它是一个定义,
x2
将为 0,并且包含标头的每个翻译单元都有自己的x2
副本。 -
是的,但它会导致链接器错误,而不是编译器。
-
与 2. 相同,但您无法修改它。
-
在类内部,
static
具有不同的含义。在那里是合法的x5
,因为它是常量整数类型,也已初始化。
- 这种特殊情况下的外部常量
- 外部常量,未命名的命名空间
- 默认情况下,非常量变量不被视为外部变量吗?
- 导出类静态常量的未解决外部符号链接错误(仅限某些项目)
- 外部常量字符串的链接错误
- 外部常量链接规范似乎被G++忽略了
- 外部常量阵列不链接
- 类使用全局外部常量变量,该变量通过内部链接定义
- 外部C结构的C++默认复制/移动赋值运算符不是常量
- 如何在另一个命名空间中使用常量定义的外部
- 何时使用外部链接初始化全局常量,避免静态初始化顺序惨败
- 头文件中的“静态”、“外部”、“常量”
- c++中的外部常量
- 当方法是来自外部的常量时,会伪造常量(例如:缓存)
- 在运行时定义的C++全局外部常量可用于多个源文件
- 为什么当在另一个文件中更改外部常量时,链接器不会失败
- 外部常量指针的常量正确性
- 初始化外部常量变量的正式方法是什么?
- 如何为不同文件中的模板参数使用c++外部常量变量
- 将结构传递给具有外部常量模板.外置是干什么用的