C++ 单例惰性初始化实现和链接似乎有冲突

C++ singleton lazy initialization implementation and linkage seems conflict

C++ Singleton design pattern遇到这个问题,了解到在c++中有两种实现单例模式的方法。

1) 在堆中分配单个实例并 return 在 instance() 调用中

2) return instance() 调用中的静态实例,这也称为惰性初始化实现。

但我认为第二种,即惰性初始化实现,是错误的,原因如下。 来自 instance() 调用的静态对象 return 具有内部链接,并且在不同的翻译单元中将具有唯一的副本。所以如果用户修改单例,它不会反映在任何其他翻译单元中。

但是有很多说法说第二种实现是正确的,我是不是漏掉了什么?

你错了,因为单例是在一个单独的翻译单元中定义的,即包含函数定义的那个returns它。这意味着所有想要使用单例的翻译单元都会向实际定义它的单例请求它,最后都使用相同的对象(正如 singleton 模式所预期的那样: -)).

实现对象名称的链接无关紧要。重要的是你用来访问对象的函数名称的链接,那个名称当然有外部链接:

thing.h:

Thing & TheThing();   // external linkage

thing.cpp:

#include "thing.h"

Thing & TheThing() { static Thing impl; return impl; }

在程序中每次使用名称 TheThing 指的是同一个实体,即在 thing.cpp.

中定义(唯一)的函数

请记住,链接是 名称 的 属性,而不是对象。

在方法的上下文中,static 关键字与链接无关。它只是影响定义变量的"storage class"。对于静态局部变量,标准明确指出:

9.3.6 A static local variable in a member function always refers to the same object, whether or not the member function is inline.

因此,将代码放在头文件还是 cpp 文件中根本无关紧要。

请注意,对于自由/非成员函数,它确实取决于函数的链接,正如 KerrekSB 指出的那样。