在 C++ 中定义全局常量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2268749/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Defining global constant in C++
提问by dimba
I want to define a constant in C++ to be visible in several source files. I can imagine the following ways to define it in a header file:
我想在 C++ 中定义一个常量以在多个源文件中可见。我可以想象以下方法在头文件中定义它:
#define GLOBAL_CONST_VAR 0xFFint GLOBAL_CONST_VAR = 0xFF;- Some function returing the value (e.g.
int get_GLOBAL_CONST_VAR()) enum { GLOBAL_CONST_VAR = 0xFF; }const int GLOBAL_CONST_VAR = 0xFF;extern const int GLOBAL_CONST_VAR;and in one source fileconst int GLOBAL_CONST_VAR = 0xFF;
#define GLOBAL_CONST_VAR 0xFFint GLOBAL_CONST_VAR = 0xFF;- 一些函数返回值(例如
int get_GLOBAL_CONST_VAR()) enum { GLOBAL_CONST_VAR = 0xFF; }const int GLOBAL_CONST_VAR = 0xFF;extern const int GLOBAL_CONST_VAR;并在一个源文件中const int GLOBAL_CONST_VAR = 0xFF;
Option (1) - is definitely not the option you would like to use
选项 (1) - 绝对不是您想使用的选项
Option (2) - defining instance of the variable in each object file using the header file
选项 (2) - 使用头文件在每个目标文件中定义变量的实例
Option (3) - IMO is over killing in most cases
选项 (3) - IMO 在大多数情况下过度杀戮
Option (4) - in many cases maybe not good since enum has no concrete type (C++0X will add possibility to define the type)
选项 (4) - 在许多情况下可能不好,因为 enum 没有具体类型(C++0X 将增加定义类型的可能性)
So in most cases I need to choose between (5) and (6). My questions:
所以在大多数情况下,我需要在(5)和(6)之间进行选择。我的问题:
- What do you prefer (5) or (6)?
- Why (5) is ok, while (2) is not?
- 你更喜欢(5)还是(6)?
- 为什么(5)可以,而(2)不行?
采纳答案by Blindy
(5) says exactly what you want to say. Plus it lets the compiler optimize it away most of the time. (6) on the other hand won't let the compiler ever optimize it away because the compiler doesn't know if you'll change it eventually or not.
(5) 准确地说出你想说的话。此外,它可以让编译器在大部分时间将其优化掉。(6) 另一方面,不会让编译器对其进行优化,因为编译器不知道您最终是否会更改它。
回答by Nikolai Fetissov
Definitely go with option 5 - it's type safe and allows compiler to optimize (don't take address of that variable :) Also if it's in a header - stick it into a namespace to avoid polluting the global scope:
绝对使用选项 5 - 它是类型安全的,并允许编译器优化(不要获取该变量的地址 :) 此外,如果它在标题中 - 将其粘贴到命名空间中以避免污染全局范围:
// header.hpp
namespace constants
{
const int GLOBAL_CONST_VAR = 0xFF;
// ... other related constants
} // namespace constants
// source.cpp - use it
#include <header.hpp>
int value = constants::GLOBAL_CONST_VAR;
回答by AnT
(5) is "better" than (6) because it defines GLOBAL_CONST_VARas an Integral Constant Expression (ICE) in all translation units. For example, you will be able to use it as array size and as case label in all translation units. In case of (6) GLOBAL_CONST_VARwill be an ICE only in that translation unit where it is defined and only after the point of definition. In other translation units it won't work as ICE.
(5)比(6)“更好”,因为它GLOBAL_CONST_VAR在所有翻译单元中定义为积分常数表达式(ICE)。例如,您将能够在所有翻译单元中将其用作数组大小和大小写标签。在 (6) 的情况下,GLOBAL_CONST_VARICE 将仅在定义它的翻译单元中并且仅在定义点之后。在其他翻译单元中,它不会像 ICE 那样工作。
However, keep in mind that (5) gives GLOBAL_CONST_VARinternal linkage, meaning that the "address identity" of GLOBAL_CONST_VARwill be different in each translation unit, i.e. the &GLOBAL_CONST_VARwill give you a different pointer value in each translation unit. In most usage cases this doesn't matter, but if you'll need a constant object that has consistent global "address identity", then you'd have to go with (6), sacrificing the ICE-ness of the constant in the process.
但是,请记住,(5)给出了GLOBAL_CONST_VAR内部链接,这意味着GLOBAL_CONST_VAR在每个翻译单元中的“地址标识”将不同,即在每个翻译单元中&GLOBAL_CONST_VAR将为您提供不同的指针值。在大多数用例中,这无关紧要,但如果您需要一个具有一致全局“地址标识”的常量对象,那么您必须使用 (6),牺牲常量的 ICE-ness过程。
Also, when the ICE-ness of the constant is not an issue (not an integral type) and the size of the type grows larger (not a scalar type), then (6) usually becomes a better approach than (5).
此外,当常数的 ICE-ness 不是问题(不是整数类型)并且类型的大小变大(不是标量类型)时,则(6)通常比(5)更好。
(2) is not OK because the GLOBAL_CONST_VARin (2) has external linkage by default. If you put it in header file, you'll usually end up with multiple definitions of GLOBAL_CONST_VAR, which is an error. constobjects in C++ have internal linkage by default, which is why (5) works (and which is why, as I said above, you get a separate, independent GLOBAL_CONST_VARin each translation unit).
(2) 不可以,因为GLOBAL_CONST_VAR(2) 中的默认情况下具有外部链接。如果你把它放在头文件中,你通常会得到多个 的定义GLOBAL_CONST_VAR,这是一个错误。const默认情况下,C++ 中的对象具有内部链接,这就是为什么 (5) 起作用的原因(这就是为什么,正如我上面所说,您GLOBAL_CONST_VAR在每个翻译单元中都有一个单独的、独立的)。
Starting from C++17 you have an option of declaring
从 C++17 开始,您可以选择声明
inline extern const int GLOBAL_CONST_VAR = 0xFF;
in a header file. This gives you an ICE in all translation units (just like method (5)) at the same time maintaining global address identity of GLOBAL_CONST_VAR- in all translation units it will have the same address.
在头文件中。这在所有翻译单元中为您提供了一个 ICE(就像方法(5)),同时保持全局地址标识GLOBAL_CONST_VAR- 在所有翻译单元中它将具有相同的地址。
回答by xninja
If you use C++11 or later, try using compile-time constants:
如果您使用 C++11 或更高版本,请尝试使用编译时常量:
constexpr int GLOBAL_CONST_VAR{ 0xff };
回答by Andras Zoltan
If it's going to be a constant then you should mark it as a constant - that's why 2 is bad in my opinion.
如果它是一个常量,那么你应该将它标记为一个常量——这就是我认为 2 不好的原因。
The compiler can use the const nature of the value to expand some of the maths, and indeed other operations that use the value.
编译器可以使用该值的 const 性质来扩展一些数学运算,以及使用该值的其他操作。
The choice between 5 and 6 - hmm; 5 just feels better to me.
5 和 6 之间的选择 - 嗯;5只是让我感觉更好。
In 6) the value is unnecessarily detached from it's declaration.
在 6) 中,该值不必要地与其声明分离。
I typically would have one or more of these headers that only defines constants etc within them, and then no other 'clever' stuff - nice lightweight headers that can easily be included anywhere.
我通常会有一个或多个这些头文件,它们只在其中定义常量等,然后没有其他“聪明”的东西——漂亮的轻量级头文件,可以很容易地包含在任何地方。
回答by MSalters
To answer your second question:
回答你的第二个问题:
(2) is illegal because it violates the One Definition Rule. It defines GLOBAL_CONST_VARin every file where it's included, i.e. more than once.
(5) is legal because it's not subject to the One Definition Rule. Each GLOBAL_CONST_VARis a separate definition, local to that file where it's included. All those definitions share the same name and value of course, but their addresses could differ.
(2) 是非法的,因为它违反了单一定义规则。它GLOBAL_CONST_VAR在包含它的每个文件中定义,即不止一次。(5) 是合法的,因为它不受单一定义规则的约束。每个GLOBAL_CONST_VAR都是一个单独的定义,在包含它的那个文件中是本地的。当然,所有这些定义共享相同的名称和值,但它们的地址可能不同。
回答by MSalters
const int GLOBAL_CONST_VAR = 0xFF;
because it is a constant!
因为它是一个常数!
回答by den bardadym
#define GLOBAL_CONST_VAR 0xFF // this is C code not C++
int GLOBAL_CONST_VAR = 0xFF; // it is not constant and maybe not compilled
Some function returing the value (e.g. int get_LOBAL_CONST_VAR()) // maybe but exists better desision
enum { LOBAL_CONST_VAR = 0xFF; } // not needed, endeed, for only one constant (enum elms is a simple int, but with secial enumeration)
const int GLOBAL_CONST_VAR = 0xFF; // it is the best
extern const int GLOBAL_CONST_VAR; //some compiller doesn't understand this
回答by Dan Olson
It depends on your requirements. (5) is the best for most normal usage, but often results in the constant taking up storage space in every object file. (6) can get around this in situations where it's important.
这取决于您的要求。(5) 最适合大多数正常使用,但往往导致每个目标文件中不断占用存储空间。(6) 可以在重要的情况下解决这个问题。
(4) is also a decent choice if your priority is guaranteeing that storage space is never allocated, but it only works for integral constants of course.
(4) 也是一个不错的选择,如果您的优先事项是保证永远不会分配存储空间,但它当然只适用于整数常量。

