const objects at module level

N

newbarker

Hello,

Very basic question here. If I have the following constants declared
in a.cpp and in b.cpp, would there be any possibility of duplicate
symbols?:

a.cpp
--------
#include <string>

const int TheNumber = 1;
const std::string TheString("Hello");

b.cpp
--------
#include <string>

const int TheNumber = 1;
const std::string TheString("Hello");

Are they not inserted into the symbol table? Previously, I've put
these into an unnamed namespace to be sure but I'm code reviewing
others' code and they're questioning the need for an anonymous
namespace, and I suspect they're correct based on my small test
programs with VC++.

Thanks,

Pete
 
J

Jeff Schwab

Hello,

Very basic question here. If I have the following constants declared
in a.cpp and in b.cpp, would there be any possibility of duplicate
symbols?:

a.cpp
--------
#include <string>

const int TheNumber = 1;
const std::string TheString("Hello");

b.cpp
--------
#include <string>

const int TheNumber = 1;
const std::string TheString("Hello");

Are they not inserted into the symbol table? Previously, I've put
these into an unnamed namespace to be sure but I'm code reviewing
others' code and they're questioning the need for an anonymous
namespace, and I suspect they're correct based on my small test
programs with VC++.

C++ constants at global scope have internal linkage by default. This is
different from C, where they have external linkage. The first reason
that comes to mind for this difference is so that C++ constants (with
proper static types) can effectively replace C-style preprocessor
constants (#define MAX 42).

Functions and non-const variables declared at global scope have default
external linkage in both C and C++.

FWIW, this surprised me, too. I group these constants into unnamed
namespaces as well, and probably will continue to do so, for reasons
vaguely akin to why I always put curly braces around loop bodies, even
when technically unnecessary.
 
N

newbarker

C++ constants at global scope have internal linkage by default.  This is
different from C, where they have external linkage.  The first reason
that comes to mind for this difference is so that C++ constants (with
proper static types) can effectively replace C-style preprocessor
constants (#define MAX 42).

Functions and non-const variables declared at global scope have default
external linkage in both C and C++.

FWIW, this surprised me, too.  I group these constants into unnamed
namespaces as well, and probably will continue to do so, for reasons
vaguely akin to why I always put curly braces around loop bodies, even
when technically unnecessary.- Hide quoted text -

- Show quoted text -

Jeff,

Thanks for the reply. I've also found Stroustrup say the same it's ok
in CPPPL3E section 9.2. (but he doesn't point out the difference with
C).

Pete
 
J

James Kanze

C++ constants at global scope have internal linkage by
default. This is different from C, where they have external
linkage. The first reason that comes to mind for this
difference is so that C++ constants (with proper static types)
can effectively replace C-style preprocessor constants
(#define MAX 42).

Which really isn't much of a reason, since you could aways write
"static const int ...", if that's what you wanted.
Functions and non-const variables declared at global scope
have default external linkage in both C and C++.
FWIW, this surprised me, too. I group these constants into
unnamed namespaces as well, and probably will continue to do
so, for reasons vaguely akin to why I always put curly braces
around loop bodies, even when technically unnecessary.

The case where it's really surprising is with regards to
templates. Something like "template< int const* PI > ..." can't
be instantiated with the address of TheNumber, above. You have
to define it:
extern int const TheNumber = 1 ;
(Put it in an anonymous namespace, and you've effectively used
"extern" to define a local variable.)
 
J

Jeff Schwab

James said:
Which really isn't much of a reason, since you could aways write
"static const int ...", if that's what you wanted.

True. Or use unnamed namespaces.
The case where it's really surprising is with regards to
templates. Something like "template< int const* PI > ..." can't
be instantiated with the address of TheNumber, above. You have
to define it:
extern int const TheNumber = 1 ;
(Put it in an anonymous namespace, and you've effectively used
"extern" to define a local variable.)

That does seem odd. Do you know of a better reason for the default
internal linkage of global-scope constants? I do not.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,066
Latest member
VytoKetoReviews

Latest Threads

Top