shared_ptr
は良い例です。オブジェクト表現をコピーすると、同じオブジェクトへの 2 番目のポインターが得られますが、使用回数は増加しません。使用回数がポインターの数と等しくなければならないという不変条件を破ると、ダングリング ポインターの逆参照や同じオブジェクトの 2 回の削除など、未定義の動作が発生する可能性があります。
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`