C++:在外部类中构造和销毁静态内部类实例

3

我是C++的新手,正在学习C++中的嵌套类和静态类成员,我编写了下面的代码:

#include <iostream>

using namespace std;

class Outter
{
public:
    Outter() {
        //get();
        cout << "construct Outter" << endl;
    }
    ~Outter() {
        cout << "destruct Outter" << endl;
    }
private:
    class Inner
    {
    public:
        Inner() {
            cout << "construct Inner" << endl;
        }
        ~Inner() {
            cout << "destruct Inner" << endl;
        }
    };
    //Inner get() {
    //    return i;
    //}
    static Inner i;
};

int main() {
    Outter o;
    return 0;
}

我在外部类中创建了一个内部类,和内部类的一个静态实例。当我不使用 get() 函数运行这段代码时,结果输出如下:
construct Outter
destruct Outter

然后我取消 get() 函数的注释,并在 Outter() 中调用它,重新运行程序,输出结果变为:

destruct Inner
construct Outter
destruct Outter

我对这个结果感到困惑,因为在我的理解中,在 destruct Outter 之前应该有一个 construct Inner,并且 destruct Inner 应该在 destruct Outter 之后。有人可以解释一下这里发生了什么吗?


我对所示代码是否能够编译和链接存在疑虑,因为静态类成员仅被声明而未被定义。 - Sam Varshavchik
@SamVarshavchik 它可以 - cigien
2
啊,我明白了为什么它编译通过了。因为这个程序会让鼻妖飞出你的鼻子。缺失的构造函数调用源于复制了不存在的对象,因此没有构造函数调用,析构函数调用源于被销毁的临时对象。所示代码仍然不规范,但编译器在这种极端情况下不需要产生错误消息。 - Sam Varshavchik
1个回答

0

输出结果不是你期望的,因为在调用getInner i;已经被构建。

发生的情况如下: 1. 在get中,您获得对i的静态实例,这是一次复制操作,没有默认构建在这里。 3. 您返回一个临时的副本Inner对象,该对象立即被销毁,因此destruct Inner

我想,Outer是不言自明的。您构造它,并且当它超出范围时它被破坏。


1
这似乎不正确。i没有在任何地方定义,即使它被定义了,构造函数也应该被调用。 - cigien
我假设这是一个不完整的代码片段,并基于此解释了为什么OP会得到令人费解的输出。 - jvd
顺便提一下,OP的代码在g++ 10下编译通过,并输出了与问题中要求相同的结果。 - jvd
3
这是因为两个编译器都会完全优化掉对未声明对象的引用,因此不会出现链接错误。如果默认的复制构造函数正式引用被复制的对象(即使从未从中复制任何内容),将会出现链接错误。 - Sam Varshavchik
我理解你的意思,我想知道是否有一种方法可以初始化这样的“静态内部类 i”。 - Harry Zhao
显示剩余2条评论

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