gpt4 book ai didi

c++ - 未命名命名空间内名称的外部链接

转载 作者:太空狗 更新时间:2023-10-29 20:23:00 26 4
gpt4 key购买 nike

根据 C++ 标准的条款 3.5/4:

An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage.

同时在第 7.3.1.1 段中我们有注释 96):

Although entities in an unnamed namespace might have external linkage, they are effectively qualified by a name unique to their translation unit and therefore can never be seen from any other translation unit.

如果标准保证无法从另一个翻译单元访问未命名命名空间内定义的名称,如何显式为未命名命名空间内的名称建立外部链接以及如何检查链接实际上是外部链接?

在哪些情况下,对未命名命名空间内的名称进行显式外部链接是有用的?

最佳答案

回复

In which cases doing explicit external linkage for name inside unnamed namespace is useful?

外部链接的需求对于 C++03 模板很重要。例如。作为模板参数的函数指针必须是指向外部链接函数的指针。例如,以下不会用 C++03 编译器编译:

template< void(*f)() >
void tfunc() { f(); }

#include <stdio.h>
static void g() { printf( "Hello!\n" ); }

int main()
{
tfunc<g>();
}

它在 C++11 编译器上编译得很好。

因此,对于 C++11,具有外部链接但翻译单元之间没有名称冲突的匿名命名空间机制仅在技术上对类是必需的。一个类具有外部链接。人们不希望必须选择保证不会出现在其他翻译单元中的类名。

在 C++11 中,规则发生了变化,这不仅适用于模板参数,还适用于匿名命名空间中的内容是否具有外部链接。在 C++03 中,匿名 namespace 具有正式的外部链接,可能除非它本身位于匿名 namespace 中(C++03 §3.5/4 最后一个破折号 + C++03 §7.3.1.1/1)。在 C++11 中,匿名命名空间具有正式的内部链接。

这对链接器来说无关紧要,因为没有 namespace 的链接,但它作为描述事物链接的正式设备很重要:

C++11 §3.5/4:

An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage. All other namespaces have external linkage. A name having namespace scope that has not been given internal linkage above has the same linkage as the enclosing namespace if it is the name of
— a variable; or
— a function; or
— a named class (Clause 9), or an unnamed class defined in a typedef declaration in which the class has the typedef name for linkage purposes (7.1.3); or
— a named enumeration (7.2), or an unnamed enumeration defined in a typedef declaration in which the enumeration has the typedef name for linkage purposes (7.1.3); or
— an enumerator belonging to an enumeration with linkage; or
— a template.


在继续回答您的其他问题之前,值得注意的是标准中的引述,

Although entities in an unnamed namespace might have external linkage, they are effectively qualified by a name unique to their translation unit and therefore can never be seen from any other translation unit.

显然错误,因为 extern "C" 实体对于其他翻译单元是可见的,无论它在哪个命名空间中声明。

令人高兴的是,据我所知,注释是非规范的,即它们不定义语言。


回复

How to explicitly make external linkage for name inside unnamed namespace

只需将非const 变量或函数声明为extern您可以将非 const 变量或函数声明为 extern "C",使链接成为外部链接,但同时使 namespace 与链接无关关注点:C语言没有。

namespace {
extern "C" void foo() {} // Extern linkage
} // namespace <anon>

void bar() {} // Also extern linkage, but visible to other TUs.

回复

how to check that linkage is actually external

好吧,链接会影响一些事情,比如可能与单一定义规则发生冲突,通常缩写为“ODR”,在 C++11 中是 §3.2。

因此,查看链接的一种方法是链接从上述源代码生成的两个目标文件,就像您有两个具有相同源代码的翻译单元一样:

C:\my\forums\so\088> g++ -c anon.cpp -o x.o & g++ -c anon.cpp -o y.oC:\my\forums\so\088> g++ main.cpp x.o y.oy.o:anon.cpp:(.text+0x0): multiple definition of `foo'x.o:anon.cpp:(.text+0x0): first defined herey.o:anon.cpp:(.text+0x7): multiple definition of `bar()'x.o:anon.cpp:(.text+0x7): first defined herecollect2.exe: error: ld returned 1 exit statusC:\my\forums\so\088> _

链接器提示 foo 的多个定义,因为对于 C 语言绑定(bind),就链接器而言,它似乎是一个非 inline 外部链接全局命名空间的成员,具有两个(可能相互冲突的)定义。

关于c++ - 未命名命名空间内名称的外部链接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35288838/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com