shared_ptr
是一个很好的例子:复制对象表示将为您提供指向同一对象的第二个指针,但不会增加使用次数。一旦你打破了使用计数必须等于指针数量的不变量,你就会让自己对未定义的行为持开放态度,例如取消对悬空指针的引用,以及两次删除同一个对象:
shared_ptr<int> good(new int(42));
shared_ptr<int> evil;
memcpy(&evil, &good, sizeof evil); // Breaking invariant
good.reset(); // Deletes object
*evil = 666; // BOOM! accesses deleted object
evil.reset(); // BOOM! deletes object a second time.
您还提到了虚函数。如果您复制派生类的基本子对象,这些可能会导致问题;结果对象将(可能)指向错误类的虚拟表:
struct Base {
virtual int f() {return 0;}
};
struct Derived : Base {
int x;
virtual int f() {return x;}
};
Base * good = new Derived;
Base evil;
memcpy(*evil, good, sizeof evil); // Base object with Derived vtable (probably)
evil->f(); // BOOM! probably accesses nonexistent member `x`