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) .
所以这样做是安全的,但并不像看起来那么容易:需要格外小心。
在 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) .
所以这样做是安全的,但并不像看起来那么容易:需要格外小心。