Summary
In C ++ 17, the easiest way to define a global constant or global variable is usually to have a built-in variable . You create it by simply pasting the following line into your header file:
inline const std::string greeting = "Hello!";
If the global constant is of literal type , prefer to use inline constexpr ( inline is optional if its a static class member) instead of inline const :
inline constexpr std::string_view greeting = "Hello!"sv;
This also works for variables, but many of the benefits no longer apply, so you can use a different method:
inline unsigned int score = 0;
More details
Firstly, there are two main advantages of dis for this method:
- It does not work until C ++ 17, so if you need compatibility with C ++ 14 or earlier, you need to do something else. The stunt template that VTT offers is compatible with old standards and should have similar semantics for built-in variables, but it is a hack that is no longer needed if you only need C ++ 17.
- Harder to compile than
If none of them is important to you, I think that this method is superior to other methods of obtaining a global constant with external reference and, for the most part, one definition in the final executable file.
A built-in variable like this is mentioned in only one file, so it is easy to change it; this is especially useful for header-only libraries. It also means that it has a value available at compile time, so the optimizer can see it and possibly eliminate some of the usage.
Using constexpr
In C ++ 17, the static members of the constexpr class constexpr automatically inline , so if your global constant should be part of the class scope, you can do something like
constexpr int favorite_number = -3;
Otherwise, you will need to tell constexpr inline , which should work. This will have the semantics described above, but also the usual benefits of constexpr , so the compiler will know that it can try to do more at compile time. For example:
#include <string_view> using namespace std::literals; inline constexpr std::string_view greeting = "Hello!"sv; inline constexpr int scrabble_points[greeting.size()] = {4, 1, 1, 1, 1, 0}; int main() { int total = 0; for (int i : scrabble_points) { total += i; } return total; }
possible with constexpr , but not only with inline , because with constexpr it knows that greeting.size() is a compile-time constant and can be used as the size of the array. 3 With optimization, this can compile only one mov and ret statement without including any copies of the string or array, because it is not needed.
With the new built-in semantics, everything that came before main could be in the header file included in several places, and still there would be no more than one copy.
Variables
The same method easily supports mutable variables, leaving const :
inline std::string player_name = "<subject name here>";
This is a global variable with external communication. Since its variable, most of the advantages of Iv mentioned above by Pete answer are gone, but some (for example, only declare the variable in one place and do not need any references) are still present. However, they may not cost a little extra compilation time and lack of compatibility with C ++ 14.
¹ For a const or constexpr compiler / optimizer can completely exclude this variable if it is not needed. Theoretically, he may decide to copy it into immediate value or something else; in practice, you probably should not worry about this, because it will only do this if it has a good reason, and this should make the final executable smaller and / or faster. You can probably configure this with -Os instead of -O3 .
² Every object file that used a constant would still have a copy, but they would be merged during the link. The only way to avoid this is with extern variables.
³ This simplified example works even without inline or with an array only const instead of constexpr , but they are useful for more complex real-world situations.