Reputation: 12245
I just joined a new C++ software project and I'm trying to understand the design. The project makes frequent use of unnamed namespaces. For example, something like this may occur in a class definition file:
// newusertype.cc
namespace {
const int SIZE_OF_ARRAY_X;
const int SIZE_OF_ARRAY_Y;
bool getState(userType*,otherUserType*);
}
newusertype::newusertype(...) {...
What are the design considerations that might cause one to use an unnamed namespace? What are the advantages and disadvantages?
Upvotes: 377
Views: 193836
Reputation: 507393
Unnamed namespaces are a utility to make an identifier be translation unit-local. They behave as if you had chosen a unique name per translation unit for a namespace:
namespace unique { /* empty */ }
using namespace unique;
namespace unique { /* namespace body. stuff in here */ }
The extra step using the empty body is important, so you can already refer within the namespace body to identifiers like ::name
that are defined in that namespace, since the using directive already took place.
This means you can have two or more free functions named, for example,help
that can exist in multiple translation units, and they won't clash at link time. The effect is almost identical to using the static
keyword used in C which you can put in the declarations of identifiers. Unnamed namespaces are a great improvement over static as they even allow making types translation-unit-local.
// perhaps declared in translation unit A
namespace { int a; }
// perhaps declared in translation unit B
static int a;
Both the declaration in the unnamed namespace and the static variable declaration are translation-unit-local, and thus won't clash at link time, but the difference is that the declaration in the unnamed namespace gets a unique name.
You might consider reading the excellent article at comeau-computing: Why is an unnamed namespace used instead of static? (Archive.org mirror).
Upvotes: 299
Reputation: 169
The usage of the unnamed namespaces is effectively the same as declaring all things in the namespaces as static
. Under the hood, it should work in a different way (adding a unique namespace to the mangled names vs. making the resulting symbols local).
In reality, GCC just treats the symbols declared in the unnamed namespace as local (i.e. as they would be declared with static
), in addition to creating a uniquely named namespace. And the namespace name is not quite unique – they are sequentially numbered in the translation unit.
Let's take these two files:
// a.cpp
namespace {
int a = 42;
}
// b.cpp
int a = 42;
And the symbol tables for them will look like this (file name is the first symbol):
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 a.cpp
0000000000000000 l O .data 0000000000000004 _ZN12_GLOBAL__N_11aE
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 b.cpp
0000000000000000 g O .data 0000000000000004 a
(I am also slightly surprised that the b.cpp
has the name unmangled!)
For comparison, here is how a named namespace gets compiled:
// c.cpp
namespace foo
{
int a = 42;
}
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 c.cpp
0000000000000000 g O .data 0000000000000004 _ZN3foo1aE
Here, the symbol is global and mangled, with the namespace prefixed.
See ABI specs for details, but I'll provide a few facts to help reading the mangled names:
The mangled name contains sequence of <thing type><name length><name>
triplets.
For namespace
, <thing type>
is N
.
For name from the declaration, <thing type>
is empty string.
Therefore, for the a.cpp
, namespace was named _GLOBAL__N_1
. (GCC just numbers the namespaces sequentially and keeps the symbols in local linkage.
In the symbol table, it is this column:
↓
0000000000000000 g O .data 0000000000000004 _ZN3foo1aE
↑
In this answer , we can see global and local linkage.
This answer corresponds to output of GCC 13.2.1 for x86_64-pc-linux-gnu
.
Upvotes: -1
Reputation: 479
Unnamed namespace limits access of class, variable, function and objects to the file in which it is defined. Unnamed namespace functionality is similar to static
keyword in C/C++.
static
keyword limits access of global variable and function to the file in which they are defined.
There is difference between unnamed namespace and static
keyword because of which unnamed namespace has advantage over static. static
keyword can be used with variable, function and objects but not with user defined class.
For example:
static int x; // Correct
But,
static class xyz {/*Body of class*/} //Wrong
static struct structure {/*Body of structure*/} //Wrong
But same can be possible with unnamed namespace. For example,
namespace {
class xyz{/*Body of class*/}
struct structure {/*Body of structure*/}
} //Correct
Upvotes: 37
Reputation: 114825
Having something in an anonymous namespace means it's local to this translation unit (.cpp file and all its includes) this means that if another symbol with the same name is defined elsewhere there will not be a violation of the One Definition Rule (ODR).
This is the same as the C way of having a static global variable or static function but it can be used for class definitions as well (and should be used rather than static
in C++).
All anonymous namespaces in the same file are treated as the same namespace and all anonymous namespaces in different files are distinct. An anonymous namespace is the equivalent of:
namespace __unique_compiler_generated_identifer0x42 {
...
}
using namespace __unique_compiler_generated_identifer0x42;
Upvotes: 141
Reputation: 2680
In addition to the other answers to this question, using an anonymous namespace can also improve performance. As symbols within the namespace do not need any external linkage, the compiler is freer to perform aggressive optimization of the code within the namespace. For example, a function which is called multiple times once in a loop can be inlined without any impact on the code size.
For example, on my system the following code takes around 70% of the run time if the anonymous namespace is used (x86-64 gcc-4.6.3 and -O2; note that the extra code in add_val makes the compiler not want to include it twice).
#include <iostream>
namespace {
double a;
void b(double x)
{
a -= x;
}
void add_val(double x)
{
a += x;
if(x==0.01) b(0);
if(x==0.02) b(0.6);
if(x==0.03) b(-0.1);
if(x==0.04) b(0.4);
}
}
int main()
{
a = 0;
for(int i=0; i<1000000000; ++i)
{
add_val(i*1e-10);
}
std::cout << a << '\n';
return 0;
}
Upvotes: 20
Reputation: 25353
The example shows that the people in the project you joined don't understand anonymous namespaces :)
namespace {
const int SIZE_OF_ARRAY_X;
const int SIZE_OF_ARRAY_Y;
These don't need to be in an anonymous namespace, since const
object already have static linkage and therefore can't possibly conflict with identifiers of the same name in another translation unit.
bool getState(userType*,otherUserType*);
}
And this is actually a pessimisation: getState()
has external linkage. It is usually better to prefer static linkage, as that doesn't pollute the symbol table. It is better to write
static bool getState(/*...*/);
here. I fell into the same trap (there's wording in the standard that suggest that file-statics are somehow deprecated in favour of anonymous namespaces), but working in a large C++ project like KDE, you get lots of people that turn your head the right way around again :)
Upvotes: 18
Reputation: 20047
An anonymous namespace makes the enclosed variables, functions, classes, etc. available only inside that file. In your example it's a way to avoid global variables. There is no runtime or compile time performance difference.
There isn't so much an advantage or disadvantage aside from "do I want this variable, function, class, etc. to be public or private?"
Upvotes: 14