动态分配的成员指针未零初始化?MSVC与GCC/Clang行为差异探究
结论:这是MSVC的bug,你的理解完全正确
问题分析
先看你提供的代码,其中T是指向Foo类double成员的指针类型:
#include <cassert> struct Foo { double v = 0; }; int main() { using T = double Foo::*; T p1 = nullptr; T p2 = T(); T p3{}; T * pp4 = new T(); T * pp5 = new T{}; assert(p1 == p2); assert(p1 == p3); assert(p1 == *pp4); // MSVC下失败 assert(p1 == *pp5); // MSVC下失败 delete pp4; delete pp5; }
针对不同初始化方式的标准行为:
p1 = nullptr:直接初始化空成员指针,值为0,这是明确的。p2 = T()和p3{}:属于值初始化,对于成员指针这类非类类型,值初始化会触发零初始化,结果就是空成员指针,因此和p1相等——这一点所有编译器的表现都符合预期。new T()和new T{}:动态分配时的括号/大括号初始化同样属于值初始化,按照C++标准,同样需要对成员指针执行零初始化,得到的指针应该等于nullptr。但MSVC中这两个动态分配的成员指针解引用后值为1,不等于nullptr,明显违反了标准要求。
关于tiny::optional的关联问题
你提到的tiny::optional内部使用placement new构造值,而placement new的这种初始化逻辑和new T()/new T{}是一致的,所以会触发同一个MSVC的bug。
内容的提问来源于stack exchange,提问作者Sedenion
相关产品推荐
相关产品推荐

