使用 CTRP 时访问访问 parent 构造函数 UB 中的 child 属性吗?
Is accessing accessing a child attribute in the parent constructor UB when using CTRP?
我制作了一个魔杖盒来解决我的问题:https://wandbox.org/permlink/qAX6SL43BvERo32Z
基本上,正如标题所暗示的那样。我正在使用 CRTP,我的基础 / parent class 构造函数使用 CTRP 中的标准方式调用 child 方法。
但是 child 方法使用它自己的 child classes 的属性,如果属于某些类型,例如 std::string,似乎会导致运行时问题(例如 MSVC 上的错误分配,以及 GCC 上的 'what(): basic_string::_M_create' / 空字符串)。
长话短说,这是UB吗?如果是这样,究竟是为什么?
任何可以就如何解决此问题提出建议的人都可以加分。我应该/可以添加 parent class 调用的 "Init" "virtual" CTRP 方法来初始化 child 变量吗?我是否应该通常避免 CTRP 在构造函数中调用 child 方法?
Is accessing accessing a child attribute in the parent constructor UB
是的,一般来说。
... when using CTRP?
是的,特别是。
If so exactly why?
因为在对象生命周期之外访问对象的行为是未定义的。在构造 base-sub 对象时,派生对象及其成员的生命周期尚未开始。
结论:CRTP 基一定不能在它们的构造函数或析构函数中执行 CRTP 魔法(即你不能执行 static_cast<Derived*>(this)
或类似操作)(并小心调用成员函数,因为它们也不能执行)一样)。
Bonus points for anyone who can give suggestions for how to tackle this problem. Should / can I add an "Init" "virtual" CTRP method that the parent class calls to initialize the child variables?
无论您是否使用 CRTP,派生的 class 构造函数都应该初始化它自己的变量。除了初始化对象的状态之外,构造函数不应该做任何额外的事情。不应该 "do fruit things".
我制作了一个魔杖盒来解决我的问题:https://wandbox.org/permlink/qAX6SL43BvERo32Z
基本上,正如标题所暗示的那样。我正在使用 CRTP,我的基础 / parent class 构造函数使用 CTRP 中的标准方式调用 child 方法。
但是 child 方法使用它自己的 child classes 的属性,如果属于某些类型,例如 std::string,似乎会导致运行时问题(例如 MSVC 上的错误分配,以及 GCC 上的 'what(): basic_string::_M_create' / 空字符串)。
长话短说,这是UB吗?如果是这样,究竟是为什么?
任何可以就如何解决此问题提出建议的人都可以加分。我应该/可以添加 parent class 调用的 "Init" "virtual" CTRP 方法来初始化 child 变量吗?我是否应该通常避免 CTRP 在构造函数中调用 child 方法?
Is accessing accessing a child attribute in the parent constructor UB
是的,一般来说。
... when using CTRP?
是的,特别是。
If so exactly why?
因为在对象生命周期之外访问对象的行为是未定义的。在构造 base-sub 对象时,派生对象及其成员的生命周期尚未开始。
结论:CRTP 基一定不能在它们的构造函数或析构函数中执行 CRTP 魔法(即你不能执行 static_cast<Derived*>(this)
或类似操作)(并小心调用成员函数,因为它们也不能执行)一样)。
Bonus points for anyone who can give suggestions for how to tackle this problem. Should / can I add an "Init" "virtual" CTRP method that the parent class calls to initialize the child variables?
无论您是否使用 CRTP,派生的 class 构造函数都应该初始化它自己的变量。除了初始化对象的状态之外,构造函数不应该做任何额外的事情。不应该 "do fruit things".