Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to correctly define constants in C++

Tags:

c++

I see a common pattern in many C++ codebases:

Header.h:

static const int myConstant = 1;

Source1.cpp:

#include "Header.h"

Source2.cpp:

#include "Header.h"

Based on:

3.5 Program and linkage

...

(2.1) — When a name has external linkage , the entity it denotes can be referred to by names from scopes of other translation units or from other scopes of the same translation unit.

(2.2) — When a name has internal linkage , the entity it denotes can be referred to by names from other scopes in the same translation unit.

...

3 A name having namespace scope (3.3.6) has internal linkage if it is the name of

(3.1) — a variable, function or function template that is explicitly declared static; or,

myConstant is accessible only from the same translation unit and the compiler will generate multiple instances of it, one for each translation unit that included Header.h.

Is my understanding correct - multiple instances of myConstant are created? If this is the case can you please point me to better alternatives of using constants in C++

EDIT:

Some suggested to make myConstant extern in the header and define it in one cpp file. Is this a good practice? I guess this will make the value invisible to the compiler and prevent many optimizations, for example when the value appears in arithmetic operations.

like image 829
Mircea Ispas Avatar asked Jul 18 '17 07:07

Mircea Ispas


2 Answers

What you're doing should be fine. The optimizer will probably avoid creating any storage for the constants, and will instead replace any uses of it with the value, as long as you never take the address of the variable (e.g. &myConstant).

like image 88
Barmar Avatar answered Oct 10 '22 22:10

Barmar


A pattern static const int myConstant = 1 arising in header files is a little bit strange, because keyword static restricts the scope of a variable definition to the specific translation unit. Hence, this variable can then not be accessed from other translation units. So I don't see why someone might expose a variable in a header file though this variable can never be addressed from "outside".

Note that if different translation units include the header, then each translation unit will define its own, somewhat "private" instance of this variable.

I think that the common pattern should be:

In the header file:

extern const int myConstant;

In exactly one implementation file of the whole program:

const int myConstant = 1;

The comments say, however, that this will prevent the compiler from optimisations, as the value of the constant is not know at the time a translation unit is compiled (and this sounds reasonable).

So it seems that "global/shared" constants are not possible and that one might have to live with the - somewhat contradicting - keyword static in a header file.

Additionally, I'd use constexr to indicate a compile time constant (though the compiler might derive this anyway):

 static constexpr int x = 1;

Because the static-keyword still disturbs me somehow, I did some research and experiments on constexpr without a static keyword but with an extern keyword. Unfortunately, an extern constexpr still requires an initialisation (which makes it a definition then and leads to duplicate symbol errors). Interestingly , at least with my compiler, I can actually define constexpr int x = 1 in different translation units without introducing a compiler/linker error. But I do not find a support for this behaviour in the standard. But defining constexpr int x = 1 in a header file is even more curious than static constexpr int x = 1.

So - many words, few findings. I think static constexpr int x = 1 is the best choice.

like image 23
Stephan Lechner Avatar answered Oct 10 '22 23:10

Stephan Lechner