在初始化列表中使用“this”指针是否安全?
我有两个具有父子关系的类( Parent
类“有一个” Child
类),而且Child
类有一个指向Parent
的指针。 在构buildsubprocess时初始化父指针会很好,如下所示:
class Child { public: Child (Parent* parnet_ptr_) : parent_ptr(parent_ptr_) {}; private: Parent* parent_ptr; }; class Parent { public: Parent() : child(this) {}; private: Child child; }
现在,我知道人们build议不要在初始化列表中使用this
, C ++ FAQ说我会得到一个编译器警告(顺便说一句,在VS2010,我没有得到警告),但我真的很喜欢这个,然后调用一些设置函数在Parent
的构造函数中。 我的问题是:
- 在创build
Child
对象时父指针是否定义良好? - 如果是这样的话,那么为什么它被认为是不好的做法,如上所述?
谢谢,
波阿斯
编辑:谢谢Timbo,这确实是一个重复 (嗯,我甚至select了相同的类名)。 所以,让我们得到一些附加价值:如何引用? 是否可以/安全地做到以下几点? :
class Child { public: Child (Parent& parnet_ptr_) : parent_ptr(parent_ptr_) {}; private: Parent* parent_ptr; }; class Parent { public: Parent() : child(*this) {}; private: Child child; }
是。 在初始化列表中使用this
指针是安全的, 只要它没有被用来直接或间接地访问未初始化的成员或虚函数 ,因为对象还没有被完全构造。 对象的child
对象可以存储Parent
对象的this
指针以备后用!
这个父指针,在“指针方面”, 是明确定义的(否则父构造函数怎么知道它在哪个实例上运行?),但是:
- 在
Child
对象之后声明的字段尚未初始化; - 构造函数中的代码还没有运行;
- 另外,关于从构造函数使用虚拟成员的常见警告应用1 。
所以,一般的父对象还处于不一致的状态, 子对象在父对象上构造的所有东西都将在一个半结构化的对象上完成,而这通常不是一件好事(例如,如果它调用“正常”方法 – 依赖于事实对象是完全构build的 – 你可能会得到“不可能”的代码path)。
不过,如果所有的子对象都在构造函数中使用父指针来存储它,以便稍后使用它(=>当它将被实际构造时),那么它没有任何问题。
- 也就是说,virtual dispatch在构造函数中不起作用,因为vtable还没有被派生类的构造函数更新。 看这里例如。
只要你不试图取消引用指针,直到Parent
对象被完全构造之后(如下面的注释中所说的@Sergey,如果构造的对象实际上是从Parent
派生的,那么所有的的build设者必须完成)。