You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

动态分配的成员指针未零初始化?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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 21:17:12