我在许多C ++代码库中看到了一个共同的模式:
Header.h:
static const int myConstant = 1;
Source1.cpp:
#include "Header.h"
Source2.cpp:
#include "Header.h"
基于:
3.5计划和联系
...
(2.1) - 当一个名称有外部链接时,它所代表的实体可以通过范围中的名称来引用 其他翻译单位或同一翻译单位的其他范围。
(2.2) - 当名称具有内部链接时,其表示的实体可以通过其他范围的名称引用 在同一个翻译单元。
...
3具有命名空间范围(3.3.6)的名称具有内部链接(如果它是
的名称)(3.1) - 显式声明为static的变量,函数或函数模板;或者,
myConstant
只能从同一个翻译单元访问,编译器会生成多个实例,每个翻译单元一个包含Header.h
。
我的理解是否正确 - 创建了myConstant
的多个实例?如果是这种情况,请指点我在C ++中使用常量的更好的替代方案
编辑:
有些人建议在标题中添加myConstant
extern
,并在一个cpp
文件中定义它。这是一个好习惯吗?我猜测这将使编译器看不到该值并阻止许多优化,例如当值出现在算术运算中时。
答案 0 :(得分:4)
你正在做的事情应该没问题。优化器可能会避免为常量创建任何存储,而是将其替换为值的任何使用,只要您从不接受变量的地址(例如&myConstant
)。
答案 1 :(得分:1)
头文件中出现的模式static const int myConstant = 1
有点奇怪,因为关键字static
将变量定义的范围限制在特定的翻译单元。因此,不能从其他翻译单元访问该变量。所以我不明白为什么有人可能会在头文件中公开一个变量,尽管这个变量永远不能从“外部”解决。
请注意,如果不同的翻译单元包含标题,那么每个翻译单元都会定义自己的,这个变量的某种“私有”实例。
我认为共同的模式应该是:
在头文件中:
extern const int myConstant;
在整个程序的一个实现文件中:
const int myConstant = 1;
然而,评论说,这将阻止编译器进行优化,因为在编译翻译单元时不知道常量的值(这听起来很合理)。
所以似乎“全局/共享”常量是不可能的,并且可能必须在头文件中使用 - 有点矛盾 - 关键字static
。
此外,我使用constexr
来表示编译时常量(尽管编译器可能会得到这个):
static constexpr int x = 1;
由于static
- 关键字仍然以某种方式扰乱了我,我在constexpr
上进行了一些研究和实验,没有static
关键字但使用extern
关键字。不幸的是,extern constexpr
仍然需要初始化(这使得它成为一个定义,并导致重复的符号错误)。有趣的是,至少在我的编译器中,我实际上可以在不同的转换单元中定义constexpr int x = 1
而不会引入编译器/链接器错误。但我没有在标准中找到对此行为的支持。但是在头文件中定义constexpr int x = 1
比static constexpr int x = 1
更加好奇。
所以 - 很多单词,很少有发现。我认为static constexpr int x = 1
是最好的选择。