在C++中,类是否可以包含指向构造函数中初始化的同一类的指针?

In C++, can a class include a pointer to the same class that's initialized in the constructor?

本文关键字:一类 指针 初始化 是否 C++ 包含指 构造函数      更新时间:2023-10-16

我知道一个类不能有同一个类的成员,例如

class Sample {
int a = 0;
Sample s; // error, object would need infinite size
};

但是为什么有指针就可以了呢?

class Sample {
// this compiles, but isn't it essentially the same
// as above? 
Sample() { s = new Sample(); } 
int a = 0;
Sample *s; 
};

允许将指针作为成员,因为指针具有固定大小(32 位应用中为 4 个字节,64 位应用中为 8 个字节),因此编译器可以在编译时知道Sample的完整大小,它不依赖于指针在运行时指向的内容。

Sample构造函数中创建Sample实例不是语法错误,因此编译器允许这样做,但它会在运行时导致无限递归循环。 所以不要这样做。

一般来说,编译器擅长检测类型问题,而不擅长检测问题。

在后一种情况下,有时是因为它不能(它怎么能知道十年后发生的事情?),有时是因为它不能真正被打扰(阅读:标准不要求它做数学上困难的事情,因为那会有点卑鄙)。

在第一个示例中,递归定义是由类型显示的问题。编译器始终知道您已经做到了。事实上,它在物理上没有办法创建一个与源代码匹配的程序:这样的东西在数学上是不可能存在的——它会永远持续下去。

但是运行时间接寻址开辟了新的机会!指针不必指向任何内容。您可以不初始化s,或将其初始化为nullptr,这很好。您可以将选择留给if,并拨打rand()电话。编译器能做的最好的事情就是分析构造函数体,看看你是否递归地实例化Sample。但是,最终,这比编译器或标准愿意在1中投入的精力要多,因此它成为您的问题。

简而言之:事情就是这样

1.如果您的构造函数主体在另一个翻译单元中怎么办?这次不是,但C++喜欢一般规则...

class Sample {
int a = 0;
Sample s; // error, object would need infinite size
};

Sample的定义在你声明Sample s;的地方尚未完成,因此编译器不知道它应该分配多少大小......它不知道什么是sizeof(Sample).

指向自身的指针,即Sample *s;是标准大小,具体取决于编译代码的目标平台。