匿名命名空间内的自由函数

时间:2014-06-30 07:42:29

标签: c++

//file.h

namespace Foo{
namespace{
   void func(){}
}
}

VS

namespace Foo{ 
   void func(){} 
}

//file2.cpp use file.h's method

这两种方法之间的调用代码(例如,在可见性方面)有什么后果(如果有的话)?

3 个答案:

答案 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中使用该功能 标题中定义的模板函数冒着未定义的风险 行为,由于违反了一个定义规则。

一般情况下,如果有的话,你应该很少 在标题中使用未命名的命名空间。