C++ 在初始化列表中使用“this”指针是否安全?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5058349/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it safe to use the "this" pointer in an initialization list?
提问by bavaza
I have two classes with a parent-child relationship (the Parent
class "has-a" Child
class), and the Child
class has a pointer back to the Parent
. It would be nice to initialize the parent pointer upon construction of the child, as follows:
我有两个具有父子关系的Parent
类(类“has-a”Child
类),并且Child
该类有一个指向Parent
. 在构造子节点时初始化父指针会很好,如下所示:
class Child;
class Parent;
class Child
{
public:
Child (Parent* parent_ptr_) : parent_ptr(parent_ptr_) {};
private:
Parent* parent_ptr;
};
class Parent
{
public:
Parent() : child(this) {};
private:
Child child;
}
Now, I know people recommend not using this
in initialization list, and C++ FAQsays I'm gonna get a compiler warning (BTW, on VS2010, I don't get a warning), but I really like this better then calling some set function in Parent
's constructor. My questions are:
现在,我知道人们建议不要this
在初始化列表中使用,C++ FAQ说我会收到编译器警告(顺便说一句,在 VS2010 上,我没有收到警告),但我真的更喜欢这个,然后调用一些 set 函数inParent
的构造函数。我的问题是:
- Is the parent
this
pointer well-defined when theChild
object is being created? - If so, why is it considered bad practice to use it as above?
- 创建对象
this
时父指针是否定义良好Child
? - 如果是这样,为什么像上面那样使用它被认为是不好的做法?
Thanks,
谢谢,
Boaz
波阿斯
EDIT:Thanks Timbo, it is indeed a duplicate(huh, I even chose the same class names). So lets get some added value: how about references? Is it possible / safe to do the following? :
编辑:谢谢 Timbo,它确实是重复的(嗯,我什至选择了相同的类名)。那么让我们获得一些附加值:引用怎么样?执行以下操作是否可能/安全?:
class Child
{
public:
Child (Parent& parnet_ptr_) : parent_ptr(parent_ptr_) {};
private:
Parent* parent_ptr;
};
class Parent
{
public:
Parent() : child(*this) {};
private:
Child child;
}
回答by Nawaz
Yes. It's safe to use this
pointer in initialization-list as long as it's not being used to access uninitialized members or virtual functions, directly or indirectly, as the object is not yet fully constructed. The object child
can store the this
pointer of Parent
for later use!
是的。this
在初始化列表中使用指针是安全的,只要它不被用于直接或间接访问未初始化的成员或虚函数,因为对象尚未完全构造。对象child
可以存储this
指针以Parent
备后用!
回答by Matteo Italia
The parent this
pointer, in "pointer terms", iswell-defined (otherwise how would the parent constructor know on which instance is it operating?), but:
this
在“指针术语”中,父指针是明确定义的(否则父构造函数如何知道它在哪个实例上运行?),但是:
- the fields that are declared after the
Child
object aren't initialized yet; - the code in the constructor hasn't run yet;
- also, the usual warnings about using virtual members from the constructor apply1.
- 在
Child
对象之后声明的字段尚未初始化; - 构造函数中的代码还没有运行;
- 此外,关于使用构造函数中的虚拟成员的常见警告适用于1。
So, the parent object in general is still in an inconsistent state; everything the child object will do on construction on the parent object, will be done on a half-constructed object, and this in general isn't a good thing (e.g. if it calls "normal" methods - that rely on the fact that the object is fully constructed - you may get in "impossible" code paths).
所以,父对象一般仍处于不一致状态;子对象在父对象上构建时所做的一切,都将在一个半构建的对象上完成,这通常不是一件好事(例如,如果它调用“正常”方法 - 依赖于以下事实:对象已完全构建 - 您可能会进入“不可能的”代码路径)。
Still, if all the child object do with the parent pointer in its constructor is to store it to be use it later (=> when it will be actually constructed), there's nothing wrong with it.
尽管如此,如果所有子对象在其构造函数中对父指针所做的都是存储它以备后用(=> 实际构造时),那么它没有任何问题。
- I.e., virtual dispatch doesn't work in constructors, because the vtable hasn't been updated yet by the derived class constructor. See e.g. here.
- 即,虚拟调度在构造函数中不起作用,因为派生类构造函数尚未更新 vtable。参见这里。
回答by Oliver Charlesworth
The behaviour is well-defined so long as you don't attempt to dereference the pointer until afterthe Parent
object has been completely constructed (as @Sergey says in a comment below, if the object being constructed is actually derived from Parent
, then allof its constructors must have completed).
该行为被明确定义的,只要你不试图取消引用指针,直到之后的Parent
对象已经完全构造(如@Sergey在评论说的下方,如果被构造的对象实际上是源自Parent
,然后所有的其构造函数必须已完成)。