在内存中逐字节覆盖多态对象在C++中是否有效?

iaqfqrcu  于 2023-06-25  发布在  其他
关注(0)|答案(1)|浏览(86)

这更像是一个“如果”的问题,而不是一个实际的问题。假设我分配了一些多态对象,分配器总是为最大的对象保留足够的空间。我想知道你是否可以使用memcpy将一个对象的多态类型更改为另一个。
从我的脑海里;未检测:

class Animal {
  virtual ~Animal() {}
};

struct Cat : public Animal {
  int lives;
};

struct Dog : public Animal {
  size_t bark_count;
};

Dog* dog = malloc(std::max(sizeof(Dog), sizeof(Cat)));
new (dog) Dog(0);

Cat* cat = malloc(std::max(sizeof(Dog), sizeof(Cat)));
new (cat) Cat(9);

// Make cat a dog. Is this possible?
memcpy(reinterpret_cast<char*>(cat), reinterpret_cast<char*>(dog), sizeof(Dog));

我假设由于问题When is a type in c++11 allowed to be memcpyed?,这是无效的行为。不过,我也不是100%确定。

**上下文:**我正在写一个类型检查器,需要在更多信息可用时“重写”类型。我考虑过将Type类重构为联合类型,但这需要大量的工作。其他方法也非常受欢迎。

mrwjdhj3

mrwjdhj31#

我假设,由于这个问题,当一个类型在c++11允许被memcpyed?,这是无效的行为。不过,我也不是100%确定。
没错。
你的类是virtual,因为它有一个非平凡的析构函数,所以它是不可平凡复制的。
因此,用memcpy复制对象表示是完全不可能的。更糟糕的是,这些类型也不是隐式生命周期,因此memcpy根本不会在cat存储中创建任何Dog对象。如果您实际使用目标缓冲区,就好像它包含Dog对象一样,那么行为至少是未定义的。memcpy本身可能没有问题,但与您如何编写示例有一些细微差别。
通过类似字符的指针逐字节地编写对象表示目前都没有被标准所涵盖。memcpy只是被指定为一个“神奇的”函数,它以某种方式复制一个对象的底层字节,如果一个普通可复制对象的所有底层字节都被复制到一个相同类型的对象中(可能是由memcpy隐式创建的),那么目标对象将拥有与源对象相同的值。
reinterpret_cast<char*>是无意义的btw。memcpy需要一个void*,并且到它的转换是隐式的。

相关问题