静态对象的私有析构函数被称为什么?

8
我正在实现以下单例模式。

可能是重复的问题:
在单例类析构函数中无法访问私有成员

我正在以下面的方式实现单例模式。

class A
{
public:

    static A& instance();
private:
    A(void)
    {
        cout << "In the constructor" << endl;
    }
    ~A(void)
    {
        cout << "In the destructor" << endl;
    }

};

A& A::instance()
{
    static A theMainInstance;
    return theMainInstance;
}

int main()
{
    A& a = A::instance();

    return 0;
 }
析构函数是私有的。当程序即将终止时,这会为theMainInstance对象调用吗?
我在Visual studio 6中尝试过,但它会给出编译错误。
"cannot access private member declared in class..."

在Visual Studio 2010中,这段代码被编译并且析构函数被调用。根据标准,这里应该有什么期望呢?
编辑:混淆的原因在于Visual Studio 6的行为并不是如此愚蠢。可以认为静态对象A的构造函数是在A的函数上下文中调用的。但是析构函数不是在同一函数上下文中被调用。它是从全局上下文中调用的。

这个例子是正确的,因为析构函数在静态变量 "类内" 被调用了。<br>但是,在编译期间,这种情况会导致错误。<br>http://liveworkspace.org/code/a13eb44e21c01a2b32bd92382722350b - Ilya Lavrenov
2
好像又是 Visual Studio 的标准把戏。如果版本 6(6?VS 6?)有这个错误,但 VS2010 没有,我怀疑这不是语言问题,而是编译器问题。 - Linuxios
5
关于MSVC 6.0:已有15年历史。发布于Windows XP、ME、Vista之前,iPad、iPhone之前,千年之际之前。在多核CPU普及之前,当MMX指令大行其道时,SSE、SSE2、SSE3、SSSE3、SSE4、AVX甚至还没有被想到。300-400 MHz就已经很高了。你只有16 KiB的L1缓存。多GB硬盘还很新颖。它是在C++98标准出现之前开发的,而这个标准已经被两次取代了。不要使用它。 - Sebastian Mach
2
我不同意这是一个完全重复的问题。被列为可能重复的那个问题是在问“为什么在VC++6中不能工作?”,而这个问题是在问“正确的行为是什么,为什么是这样?” - Vaughn Cato
我认为编译器会将析构函数添加到atexit() LIFO堆栈中,并在程序退出时调用它。这将发生在具有构造函数的静态对象或具有非编译时常量初始化程序的静态基元内部的函数中。 - User 10482
显示剩余5条评论
1个回答

5
C++03规范的第3.6.3.2节指出:
在从main函数返回或调用exit函数时,会调用具有静态存储期(在块作用域或命名空间范围声明)的初始化对象的析构函数。
它并没有限制私有析构函数的使用,因此如果创建了实例,也将被销毁。
但是,私有析构函数确实对声明对象的能力造成了限制(C++03 12.4.10):
如果声明了类类型的对象或其数组,且该类的析构函数在声明点不可访问,则该程序无效。
但由于A::theMainInstance的析构函数在声明点可访问,所以你的示例应该没有错误。

我不想说,但他正在使用1998年发布的Visual Studio 6.0 :( - Sebastian Mach
@phresnel:没错。我理解这个问题是“什么是正确的行为”。他尝试了两个不同的版本并得到不同的结果,想知道哪一个是正确的,并想知道原因。 - Vaughn Cato
@VaughnCato:那正是我的问题。 - PermanentGuest

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接