//file.h
namespace Foo{
namespace{
void func(){}
}
}
VS
namespace Foo{
void func(){}
}
//file2.cpp use file.h's method
这两种方法之间的调用代码(例如,在可见性方面)有什么后果(如果有的话)?
答案 0 :(得分:4)
此:
namespace Foo {
namespace {
void func() {}
}
}
在很大程度上与此相同:
namespace Foo {
static void func() {}
}
不同之处在于static
情况下,函数具有内部链接,因此链接器不可见。在未命名的命名空间的情况下,该函数具有外部链接(链接器可见),但在一个名称下,您的其他源文件都不能正常#34;通常"访问。如果您对编译器的名称修改方案进行反向工程,您仍然可以从不同的源文件中调用该函数,并且该函数仍然列在目标文件的符号中,例如。
但常见的是,包含代码的每个源文件(可能通过#include
头文件)都将包含自己的函数副本。这会对二进制文件的大小产生影响。
此外,如果由于某种原因需要第一个,你应该大量记录它。头文件中的未命名命名空间通常是" WTF"点,你不希望这些在你的代码中。我必须说我无法想到一个可行的用例。
答案 1 :(得分:1)
两种变体都允许在名称Foo::func()
下找到该功能。
但是,编译器可能会在这两种情况下生成不同的代码。在匿名命名空间内声明一个函数会使该函数成为.cpp
文件的本地函数。也就是说,包含标头的每个.cpp
文件可能最终都有自己(相同)的func
代码实例化。由于重复的代码,这可能会导致最终可执行文件中出现一些膨胀。
请注意,如果您定义内联函数(正如您的问题所示),这不是一个真正的问题,因为代码将因内联而重复。
然而,正如评论中所指出的:标题中的匿名名称空间是不寻常的,并且会引起对此代码的评论的怀疑。你应该总是喜欢第二种选择,除非你有充分的理由不这样做。
答案 2 :(得分:1)
第一个相当于:
namespace Foo
{
namespace TranslationUnitSpecific
{
void func();
}
}
这意味着每次包含标题时,都会声明
一个新的,不相关的func
实例。如果func
不是inline
,
您必须在使用它的每个源文件中定义它。
(另一方面,它确实意味着你可以提供一个
头部中的实现没有使功能
inline
。)
这也意味着您无法在inline
中使用该功能
标题中定义的模板函数冒着未定义的风险
行为,由于违反了一个定义规则。
一般情况下,如果有的话,你应该很少 在标题中使用未命名的命名空间。