1

Let say I have an header file Resources.h where I have defined these 5 structs:

const IColor COLOR_BLACK(255, 0, 0, 0);
const IColor COLOR_GRAY(255, 127, 127, 127);
const IColor COLOR_WHITE(255, 255, 255, 255);
const IColor COLOR_RED(255, 255, 0, 0);
const IColor COLOR_GREEN(255, 0, 255, 0);

Using const (static by default in C++, so internal linkage) they "reside" in the scope of a translation unit.

Now, let say I include this files 10 times into my application (from 10 different .cpp). When I compile, an object file is created, and (later) the Linker will gather all these object files together into a unique runnable code for the machine.

Does this means that when I run the program, it will allocate in memory 10 times each structs above? i.e. 10x5 structs?

So they are separate for translation unit even when they are linked together later? Or linker is smart enough to converge them to a unique allocation in memory?

Not sure if I got these steps corerctly. I'm fancy new in C++.

markzzz
  • 47,390
  • 120
  • 299
  • 507

3 Answers3

2

Yes. But (1) a handful of bytes is nothing against the usual size of even the smallest executable, and (2) it will probably be optimized away anyway. If you want to avoid even that, use constexpr, which makes them compile time values only.


In other news, a common convention in C++ is to use all uppercase identifiers for macros only. That's because all uppercase is an eyesore, so that convention should be reserved for things that also are generally ungood. When you use all uppercase for anything else you (1) appear to shout, to many programmers, and (2) risk inadvertent text substitution, and (3) risk miscommunicating what those names stand for.

C++ is not Java or Python.

Those languages got the convention of all uppercase for constants from early C, which didn't have const so that they had to express constants as preprocessor macros. I.e., the Java and Python convention is really the uppercase-for-macros convention from C. Using macros for constants is obsolete in C++, and, unlike those languages, C++ does have a preprocessor.


Also, beware: the prefix I for a type is a common convention for indicating an (abstract) interface, but per your declarations IColor must be a concrete, instantiable type.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
0

Remember: the standard only specifies the behaviour of an abstract machine. Actual implementation are not required to emulate the abstract machine, but only its observable behaviour.

So for the abstract machine an instance of every internal linkage variable will be allocated per translation unit. But as they are const, it is likely that you only use their value and not they address - in standard terms they will probably not be odr-used (one definition rule). In that case, they will be processed by the compiler as is they were just compile time constants and no memory at all will be allocated for them: they will be replaced with they value by the compiler.

The only case where you should considere manual optimization would be IMHO when the const value are expensive in size or construction time. Then in makes sense to declare them extern in the header, and define them in only one translation unit.

If it is not the case, as they have internal linkage, this is not a violation for the one definition rule which would happen if they were defined with external linkage in different translation units.

TL/DR: In all normal use cases, just use the idiom an go on. And if you are really very short in memory, just control the generated assembly code: it is likely that those variables will be optimized away and replaced with their value.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
0

You might have 10 of them at the compilation stage but they might get optimized out eventually on the linking stage.

Still, you can try a different approach for such const variable definitions in case you need to be sure due to some memory limitations.

Having your header file, put there only the variable declarations as extern.

// my_consts.h
extern const IColor COLOR_BLACK;

Then make a source file where the actual definitions appear.

// my_consts.cpp
const IColor COLOR_BLACK(255, 0, 0, 0);

This way the actual definitions are compiled once and you can still refer to them since you have them declared in the header file.

Additionally, having such constants it would be nice to stick them into some namespace to avoid global namespace pollution - especially if you can divide them in some logical categories.

Dusteh
  • 1,496
  • 16
  • 21