【发布时间】:2022-01-01 05:51:38
【问题描述】:
鉴于此代码:
#include <cassert>
#include <cstring>
struct base{
virtual ~base() = default;
};
class derived: public base{
public:
int x;
};
using byte = unsigned char;
int main() {
byte data[sizeof(derived)];
derived d;
memcpy(data, &d, sizeof(derived));
base* p = static_cast<base*>(reinterpret_cast<derived*>(data));
const auto offset = (long)data - (long)p;
assert(offset < sizeof(derived)); // <-- Is this defined?
}
正如我的评论所问的,这是标准定义的行为吗?即,转换为基础是否保证指向派生被转换所占用的区域的指针?根据我的测试,它适用于 gcc 和 clang,但我想知道它是否也适用于跨平台(显然这个版本假定 64 位指针)
【问题讨论】:
-
您不想放置新位置而不是
memcpy。static_cast<base*>应该不是问题,但reinterpret_cast<derived*>应该是强制转换(缓冲区中没有对象)。 -
@Jarod42 在我的实际代码中,我使用placement new 并手动调用dtor 和placement copy 构造等,这只是为了举例。此外,memcpy 应该是有效的 afaik,该 int 的值将是垃圾,因为它未初始化但它的数据仍被分配(在堆栈上)
-
读取未初始化
x是另一个问题(作为对齐的潜在问题);我的观点是,在缓冲区data中没有对象(任何derived实例的生命周期都没有开始)。不过,placement new 是正确的,这只是您对“有问题”的问题的简化。