Sign in to follow this  
Red Ant

Confused about constants defined in namespaces

Recommended Posts

Hi, I used to operate under the assumption that in C++, constants defined in a header file ... like so
// Constants.h
namespace Constants
{
    const int theInt = 6;
}

would be shared by all compilation units including this header. That is, instead of each compilation unit getting its own copy of theInt, all compilation units including Constants.h would share one copy of theInt. However, I just compiled a minimal project (Visual C++ 2005) that has 2 compilation units CompilationUnit1.cpp and CompilationUnit2.cpp that both pull in Constants.h and then print the address of Constants::theInt, and surprisingly the addresses did not match! :o What do I need to do if I want all compilation units to share the same instance of Constants::theInt?

Share this post


Link to post
Share on other sites
Hmm, apparently if I declare theInt 'extern' and then initialize it in a separate cpp (Constants.cpp), all compilation units really get to share the same copy of theInt. Is that the recommended way of sharing constants across compilation units?

Share this post


Link to post
Share on other sites
Quote:
Original post by Red Ant
Is that the recommended way of sharing constants across compilation units?

The recommended way for integral constants is to refrain from taking their addresses, then they don't even consume any memory in the first place (in most cases).

Share this post


Link to post
Share on other sites
Quote:
Original post by DevFred
The recommended way for integral constants is to refrain from taking their addresses, then they don't even consume any memory in the first place (in most cases).


Ah okay, so I can continue just declaring my constants like this


// constants.h
namespace Constants
{
const int a = 4444;
const bool x = true;
}





and then pull in constants.h where ever I need to access them? I was just worrying that I'd unnecessarily increase my memory footprint by having each compilation unit use its own copy of each constant.

Share this post


Link to post
Share on other sites
Quote:
Original post by DevFred
Quote:
Original post by Red Ant
Is that the recommended way of sharing constants across compilation units?

The recommended way for integral constants is to refrain from taking their addresses, then they don't even consume any memory in the first place (in most cases).


Even better: Use an enum.


// Constants.h
namespace Constants
{
enum { theInt = 6 };
}


Now it is even forbidden to take the address, and you are guaranteed that this is a pure compile time construct. No need to kludge with extern or static keywords.

Share this post


Link to post
Share on other sites
Quote:
Original post by phresnel
Even better: Use an enum.



I do where ever possible but sometimes you need a const double, bool or whatever.

Share this post


Link to post
Share on other sites
Quote:
Original post by Red Ant
I do where ever possible but sometimes you need a const double, bool or whatever.


Bool will also work:
enum { is_little_endian = true };


But you are right about non integral types. The only "hardened" solution that comes to mind is to use #define macros, but that I'd avoid (just alone because of scoping issues). For my code, const-float duplication is not so relevant, so I just sticked to static const floats and doubles.

If duplication is an issue, then of course make them extern, and put the definitions into a file named "constants.[cpp|cc|cxx|etc.]" or give it a finer grained name like "planet-size-constants.[...]".

edit: typo

[Edited by - phresnel on March 12, 2009 7:54:40 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Red Ant
I was just worrying that I'd unnecessarily increase my memory footprint by having each compilation unit use its own copy of each constant.


This doesn't happen because in general (what DevFred was alluding to) the constant will simply be inlined at each point of usage when possible, and then the static constant value will be recognized as a "dead" value and optimized out of the binary. But as soon as you try to take the address of the constant, it has to exist so that it can have an address, and won't be optimized out.

Share this post


Link to post
Share on other sites
Minor Addition: If you have static const member variables of type float, you have to implant them in some translation unit. Just happened to me this morning, when I added a generic version of an epsilon- and an infinity- constant.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this