谁负责销毁块作用域的静态 Singleton 实例?
我无法理解下面的程序如何成功编译。
class SomeClass {
public: /** Singleton **/
static SomeClass &instance() {
static SomeClass singleInstance;
return singleInstance;
};
private:
SomeClass() = default;
SomeClass(const SomeClass&) = delete;
SomeClass &operator=(const SomeClass&) = delete;
~SomeClass() {}
};
int main()
{
SomeClass::instance();
// SomeClass::instance().~SomeClass(); // Compiles if destructor was public
return 0;
}
- 谁负责调用 Singleton 的析构函数 实例?
- 底层机制如何访问私有方法?
I couldn't understand how the program below compiles successfully.
class SomeClass {
public: /** Singleton **/
static SomeClass &instance() {
static SomeClass singleInstance;
return singleInstance;
};
private:
SomeClass() = default;
SomeClass(const SomeClass&) = delete;
SomeClass &operator=(const SomeClass&) = delete;
~SomeClass() {}
};
int main()
{
SomeClass::instance();
// SomeClass::instance().~SomeClass(); // Compiles if destructor was public
return 0;
}
- Who is responsible for calling the destructor of the Singleton
instance? - How does the underlying mechanism access a private method?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不久,在构造过程中,编译器将析构函数保存到将在程序最后调用的函数列表中。最后,包括析构函数在内的函数列表被一一调用,并发生安全销毁。
底层机制
该机制的核心是 C 标准库提供的
exit()
和atexit(..)
函数。在程序编译期间,编译器会在块范围静态变量周围注入一些其他代码。伪表示如下。这里的要点是调用
atexit(~SomeClass())
并将析构函数注册到exit()
函数的自动调用列表中,该函数在返回时隐式调用来自main(..)
。由于使用函数指针而不是直接引用私有析构函数方法,因此跳过了访问说明符保护机制。Shortly, during the construction, the compiler saves the destructor to a list of functions that will be called at the very end of the program. In the end, the list of functions, including the destructors, are called one by one and the safe destruction occurs.
Underlying Mechanism
The core of the mechanism is the
exit()
andatexit(..)
functions provided by the C standard library. During the compilation of the program, the compiler injects some other codes around your block-scoped static variable. A pseudo representation is as below.The point here is to call the
atexit(~SomeClass())
and register the destructor to the automatic call list of theexit()
function which is implicitly called when you return from themain(..)
. As the function pointers are used instead of directly referring to the private destructor method, the access specifier protection mechanism is skipped.