You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
An unnamed namespace or a namespace declared directly or indirectly within an unnamed namespace has internal linkage. All other namespaces have external linkage.
C++ Core Guidelines [SF.22] 推荐优先使用 Unnamed namespaces,内容如下:
Nothing external can depend on an entity in a nested unnamed namespace. Consider putting every definition in an implementation source file in an unnamed namespace unless that is defining an “external/exported” entity.
Use of internal linkage in .cc files is encouraged for all code that does not need to be referenced elsewhere. Do not use internal linkage in .h files.
那么在头文件中使用有何隐患呢?
首先,可能会违背 ODR。在同一 TU 中,多个 Unnamed namespaces 使用的是同一名称。这意味着以下示例中,a 被定义了两次,一个源文件中引用该头文件将导致 ODR 错误。
其次,可能会产生奇怪的结果。例如:
一共有两个 TUs,val 处于 Unnamed namespace,属于 Internal Linkage,而 get_value() 属于 External Linkage。两个 TUs 共用同一份 get_value() 函数,而 val 是各有各的,返回结果时将产生不可预料的结果。
测试的结果如下:
最后,还可能会导致代码膨胀。包含 Internal Linkage 的每个 TUs 都会有一份拷贝,致使可执行文件膨胀。
T240725 Unnamed namespaces - CppMore
https://ift.tt/Cu1YLJT
Li Miu
Unnamed namespaces,也叫 Anonymous namespaces,是命名空间的一种特殊形式。这种形式可以省略命名空间的名称,如:
在语义上与等价于:
编译器会自动生成一个唯一的名称,并使用 using-directives 自动导入名称。
与其他形式的命名空间不同,Unnamed namespaces 的链接方式是 Internal Linkage,标准描述为:
注意,Unnamed namespaces 里面的所有内容都是 Internal Linkage,即便是用
extern
。Global
static
的作用也是 Internal Linkage,Unnamed namespaces 可以作为它的一种替代方式。主要是static
所赋予的意义太多,有十几种用法,而 Unnamed namespaces 是一种专门用于控制全局可见性的方式。C++ Core Guidelines [SF.22] 推荐优先使用 Unnamed namespaces,内容如下:
LLVM Coding Standards 也推荐使用 Unnamed namespaces,它更加通用,不仅支持变量、函数,也支持类型(
static
不能用在struct/class
前面)。但是,它也有一个问题,就是当代码过长时,很难看出一个随机位置的实体(变量/函数/类型)是否处于 Unnamed namespaces 当中,必须扫描文件中的大部分内容。因此,LLVM 推荐尽量将 Unnamed namespaces 的范围缩小,仅在类声明时使用。Unnamed namespaces 当然也有其他问题,比如无法在空间之外特化模板:
这也是为何又引入了
inline namespace
,否则的话在这种情境下又必须使用static
。2024-07-17 补充:
Google C++ Style Guide 不建议在头文件使用 Unnamed namespaces,描述如下:
那么在头文件中使用有何隐患呢?
首先,可能会违背 ODR。在同一 TU 中,多个 Unnamed namespaces 使用的是同一名称。这意味着以下示例中,
a
被定义了两次,一个源文件中引用该头文件将导致 ODR 错误。其次,可能会产生奇怪的结果。例如:
一共有两个 TUs,
val
处于 Unnamed namespace,属于 Internal Linkage,而get_value()
属于 External Linkage。两个 TUs 共用同一份get_value()
函数,而val
是各有各的,返回结果时将产生不可预料的结果。测试的结果如下:
最后,还可能会导致代码膨胀。包含 Internal Linkage 的每个 TUs 都会有一份拷贝,致使可执行文件膨胀。
可见,主要原因集中于 Unnamed namespaces 的反直觉行为,放到头文件中易于出错。但万事无绝对,只要能够避免这些潜在的问题,使用也无妨。比如 nlohmann json issue 552 就在头文件中用了如下代码:
这里是
constexpr
引用对象,而非constexpr
变量,后者在 file scope 下默认是 Internal Linkage,而前者是 External Linkage,并且不会隐式const
。因此,代码中显式添加了const
,并且将定义全部放在 Unnamed namespace 当中,以改变链接方式。via CppMore https://www.cppmore.com
February 12, 2025 at 03:35PM
The text was updated successfully, but these errors were encountered: