关于带自引用的C++类

Fer*_*eak 5 c++ exception class

我有点困惑......

为什么在C++中允许这样做:

static int t = 0;

class A
{
    public:
        A() : m(t++)
        {

            cout << "C:" << m << endl; 
            if(t >= 5)
            {
                A a;                      // <<<< ----- THIS line
                throw( a);
            }
        }            

        int m;
};
Run Code Online (Sandbox Code Playgroud)

但这不是:

static int t = 0;

class A
{
    public:

        A() : m(t++)
        {

            cout << "C:" << m << endl; 
        }

        A a;                            // <<<< ----- THIS line

        int m;
};
Run Code Online (Sandbox Code Playgroud)

第二个没有按预期编译(是的,我知道它为什么不编译:在代码中的那个点A仍然是不完整的)...

但是......第一个编译得很好(并做了它应该做的事情,即:在类似的语句上崩溃应用程序A a[10];).是A构造函数中的完整类型吗?对于这种情况,还能指出一些C++标准条目吗?

raj*_*dit 5

当您声明任何变量时,编译器应该知道它的大小.在第二个示例的情况下,您正在创建A内部对象,A因此编译器将无法计算A分配内存的大小.


Sha*_*our 3

还可以为我指出一些针对这种情况的 C++ 标准条目吗?

是的,C++ 标准草案规定类在结束之前才完全定义},这在9.2 类成员部分第2段中:

在类说明符的结尾 } 处,类被视为完全定义的对象类型 (3.9)(或完整类型)。[...]

并且类的所有非静态数据成员必须完整,从第9段开始:

非静态(9.4)数据成员不得具有不完整的类型。特别是,类 C 不应包含类 C 的非静态成员,但它可以包含对类 C 的对象的指针或引用。

但它在构造函数中也被认为是完整的,也在第2段中:

[...]在类成员规范中,该类在函数体、默认参数、[...]中被视为完整的

尽管静态成员可能不完整,但9.4.2 静态数据成员2节:

静态数据成员在其类定义中的声明不是定义,并且可能是除 cv 限定的 void 之外的不完整类型。[...]

不允许类包含自身也是有意义的,因为这将需要无限的空间,因为自引用永远不会结束,A包含A其中包含A...