reinterpret_cast / static_cast 和未定义行为

7
在我正在开发的变体类中,原始存储是一个char数组:
alignas(/* the strictest alignment of all types of the variant */)
char storage[/* ... */];

赋值运算符类似于:
template<class X>
void operator=(const X &x)
{
  // ...code for clearing the storage and setting the tag for type X...

  new(storage) X(x);
}

获取存储对象的代码如下:

template<class X>
const X &get()
{
  // ...
  return *reinterpret_cast<X *>(storage);
  // ...
}

看起来它可以工作,但它是否总是定义良好的?我担心安全地引用指针(类型别名规则允许吗?)。

当前实现与之间是否存在任何差异?

 return *static_cast<const X *>(static_cast<const void *>(storage));

相关问题/回答:

https://dev59.com/9VrUa4cB1Zd3GeqPpP-y#7321815(参见James Kanze的评论)。


编辑

第二个问题已经在这里有了一个答案:C++ When should we prefer to use a two chained static_cast over reinterpret_cast


当然,这个 new(storage) X(x); 是一个内存泄漏。 - Ed Heal
1
@EdHeal 它通过使用放置 new 在存储器中构造 X。这应该是对齐存储的安全实践(例如:https://dev59.com/6lPTa4cB1Zd3GeqPfxHT)。您能添加一些细节吗? - manlio
1个回答

4
由于storage已经正确对齐,我无法想象出问题可能出现在哪里。指针转换的第4.10段(*)说:类型为“指向cv T”的prvalue(其中T是对象类型)可以转换为类型为“指向cv void”的prvalue。将指向对象类型的非空指针值转换为“指向cv void”的结果表示与原始指针值在内存中的同一字节的地址
关于您的第二个问题,第5.2.10段有关reinterpres_cast的说明: 对象指针可以显式地转换为不同类型的对象指针。当对象指针类型的prvalue v被转换为对象指针类型“指向cv T”时,结果是static_cast<cv T*>(static_cast<cv void*>(v)),其中cv表示可选的constvolatile
因此,这部分根据规范是有保证的。正如我们所看到的,将指针强制转换为void *应该指向内存的第一个字节,对于我对标准的理解来说没有未定义行为...前提是编译器有相同的理解 ;-)
(*) 参考文献:当前C++规范草案

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接