1

I've seen several posts about this issue, but none of them explains well my concern, so I'll try to explain here what I understand and please correct me if I'm wrong.

Suppose I have a header file with the following declaration:

//definitions.h
extern const float fallingTime; 

Now, I have two source files that want to use this declaration.

//source1.cpp
#include "definitions.h"
const float fallingTime = 0.5f;
//use fallingTime 

//source2.cpp
#include "definitions.h"
//just use fallingTime (no definition required)

This is what I do; but now, assume this other way to proceed.

//definitions.h
const float fallingTime = 0.5f; //Note that I don't use extern now

//source1.cpp
#include "definitions.h"
//just use fallingTime (no definition required)

//source2.cpp
#include "definitions.h"
//just use fallingTime (no definition required)

As I concluded from reading several sources, the advantages of the former approach is that it saves memory and compilation time, because memory allocation only occurs one (in the definition in source1.cpp), whereas in the latter approach memory allocation happens in every source file that includes definitions.h (source1.cpp and source2.cpp). Is that correct?

Finally, what would imply using extern and defining the constant at the same time? Would be equivalent to the former approach?

//definitions.h
extern const float fallingTime = 0.5f;
Francis Moy
  • 185
  • 9

2 Answers2

1

When const float fallingTime = 0.5f; is defined in a header, a translation unit may or may not store the value in the data section of your binary.

If no code in a translation unit takes an address or reference to fallingTime there is no reason for the compiler to allocate the value in the data section at all. The compiler is likely to replace usage of fallingTime with its value because its definition is available in every translation unit at compile time.

With extern const the generated code will have to load the value of fallingTime from memory because its definition is not available at compile time in any other translation unit but the one that defines the value of fallingTime.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • So, are you saying that under those circumstances both ways are equivalent in memory and compilation time? – Francis Moy Sep 23 '14 at 07:13
  • @FrancisMoy Updated the answer for you. – Maxim Egorushkin Sep 23 '14 at 08:52
  • Ok, my reasoning was mistaken. Then, if the second approach may be more optimal (from the compilation time / memory point of view), why is it usually suggested as best practice the first approach? Which is the advantage of using extern then for constants? The only problem of the second approach would be the one explained by @TomTanner? – Francis Moy Sep 24 '14 at 10:17
  • @FrancisMoy _Why is it usually suggested as best practice the first approach?_ - Where? _The only problem of the second approach would be the one explained by TomTanner_ - I do not think his answer is accurate. – Maxim Egorushkin Sep 24 '14 at 10:44
  • Regarding the best practice, I've just read it in several posts (including here: http://stackoverflow.com/questions/9649405/c-best-practices-for-constants), but I guess it's not as "best practice" as I thought in the first place. So, just to wrap up: the second approach allows some compiler optimizations for the generated code (constants propagation), but it could entail longer compilation times because each .cpp must be recompiled when the definition of the constant changes. In case of using extern, we would have the opposite implications. Can we agree on that? – Francis Moy Sep 24 '14 at 11:33
  • 1
    @FrancisMoy Well, `const` at global and namespace-scope level implies internal linkage, i.e. `static const` is the same as `const`, but not `extern const`. This behaviour was specifically implemented in C++ to avoid using macros for constants, http://stackoverflow.com/a/998457/412080... Agree with you. – Maxim Egorushkin Sep 24 '14 at 21:34
-2

The problem with the latter one is that under C++ prior to C++11 depending on your compiler, you could get a linktime error as there's no address for fallingTime. The language requires that you instantiate it in precisely one translation unit and gcc in particular is quite strict about that.

Tom Tanner
  • 9,244
  • 3
  • 33
  • 61
  • Sorry I didn't understand. With the "latter one", do you refer to using extern and the definition together? – Francis Moy Sep 22 '14 at 09:24
  • @FrancisMoy the code in "assume this other way to proceed" – Tom Tanner Sep 22 '14 at 09:48
  • So, with extern (external linkage), we're forcing that the constant is assigned a memory address, which can be necessary if taking a reference or the address of the constant, right? – Francis Moy Sep 23 '14 at 07:17
  • no. the only thing that forces a memory address is to define it in a source file (more or less. there are subtleties) – Tom Tanner Sep 23 '14 at 10:00
  • Global and namespace-scope `const` objects have internal linkage (implicit `static` applied) since C++98, the declaration is the definition, no other definitions are necessary. Unless explicitly marked as `extern`. Your answer is incorrect. – Maxim Egorushkin Sep 24 '14 at 10:53
  • the version of gcc we have insists you provide an instance. It may be aa bug in that version, but it's not one we're likely to change off soon – Tom Tanner Sep 24 '14 at 12:38