C++ 基 class 存储 'this' 的值以供将来构造后的虚拟调用安全吗?

Is it safe for a C++ base class to store the value of 'this' for future virtual calls after construction?

在 C++ 的 Base 构造函数中,'this' 的实际类型是 'Base' 而不是 'Derived',因此调用虚函数是不安全的。但是,基 class 在基构造期间将 'this' 的 值传递给将在将来调用虚函数的回调对象是否安全施工完成后?

在构造函数中调用虚拟方法并非不安全,因为 this 属于 Base 类型,但因为对象尚未完全构造。 Derived 成员此时未初始化,因此在 Derived 中执行虚方法实现将对未初始化的实例进行操作。

这就是为什么标准规定在 constructor/destructor 调用期间 the function called is the final overrider in the constructor’s or destructor’s class and not one overriding it in a more-derived class

您可以安全地存储它并从它完全构建的那一刻起调用它的虚函数,即在构造函数退出之后(那些在 Base class 上定义的虚函数,当然)。

是的,很安全。该对象不会在内存中移动。实际上,vtable ptr 将被更新,但仍然可以从您保存的未更改的 this 指针访问它。

this 指针存储在基 class 的构造函数中供以后使用是安全的,但仅在以下条件下

  • 如果指针存储在对象中,则执行 rule of 3 or the rule of 5
  • 确保移动对象(即移动构造或移动赋值)将更新存储的地址。例如,您的对象可以在 vector 中创建:矢量增长可能导致对象在调用回调之前为 relocated/moved。
  • 确保销毁对象会清除存储的地址,以防止使用悬挂指针的回调函数。
  • 在任何可能导致构造失败的语句(例如由于异常)之后,将指针存储在构造函数中。失败的构造对于回调来说可能非常糟糕,因为构造函数中的异常会导致对象不存在(即不应调用回调),因此不会调用析构函数(查看更多详细信息 here and here) .

所以这样做是安全的,但并不像看起来那么容易:需要格外小心。