为什么不能用memcpy复制非POD对象?

Why can't non-POD objects be copied with memcpy?

本文关键字:POD 对象 复制 不能 memcpy 为什么      更新时间:2023-10-16

根据我阅读的各种来源,以下C++代码调用未定义的行为:

class A {
public:
    virtual void method () {
        std::cout << "Hello" << std::endl;
    }
};
...
A *a, *b;
// obtain 2 Instances from somewhere, then...
memcpy (a, b, sizeof(A));
a->method();

为什么这会导致未定义的行为?我看不到该语言的逻辑实现会不按预期运行(在两个对象都具有相同运行时类型的情况下),那么为什么语言设计者选择不定义它呢?

memcpy执行浅层复制。在一般情况下,对于不可复制的类型,执行浅层复制是不安全的,例如,因为该类型有一个需要执行特殊操作的复制构造函数。

当然,你可以举一个例子,使用memcpy的浅拷贝实际上"有效",但标准必须列出所有允许的情况,这需要知道所有有效的实现选择,并评估什么是有效的。

相反,标准只是说你不能这样做,这是IMHO的正确选择。

使用memcpy复制原始字节。使用复制构造函数来复制对象。这是一条简单、合乎逻辑的规则。

为什么这会导致未定义的行为?

因为该语言没有指定多态性是如何实现的,因此不能指定多态类型是可复制的。

我看不出该语言的逻辑实现不会像预期的那样运行

多态性可以实现为从对象地址到类型信息的映射,而不是存储在每个对象中的指针。人们可能会争论这是好是坏,但这肯定不是不合逻辑的。

为什么语言设计者选择不定义这个?

这样就不会限制多态性更好实现的可能性。你看不到替代品并不一定意味着它们不存在。

如果使用memcpy,则绕过对象的复制构造函数。这会使您的程序处于不连贯的状态(也称为未定义的行为)。