例として、次のクラス定義があると仮定します。
class Container {
public:
// construct a container instance by making it point to an item
Container(Item *pItem) : m_pItem(pItem) { }
private:
Item *m_pItem;
};
class Item {
public:
change() {
// do something to change the item
}
private:
// some private data
};
最大で1回:特定のオブジェクトへのポインタは、任意の時点で最大1つのコンテナオブジェクトに存在できます。
Container
の同じインスタンスへのポインタを持つの2つのインスタンスがあると、Item
これに違反します。
Item *pItem = new Item(); // construct a new Item
Container c1(pItem); // create a new container pointing to this item
Container c2(pItem); // WRONG: create another container pointing to the same item
存在:オブジェクトへのポインタを挿入する前に、オブジェクトを動的に割り当てる必要があります。
オブジェクトを動的に割り当てるということは、通常、演算子を使用してオブジェクトの新しいインスタンスを作成することを意味します。演算子new
は、(スタックではなく)ヒープメモリに割り当てられた新しく作成されたオブジェクトへのポインタを返します。これに対する違反の2つの例は次のとおりです。
Item *pItem = NULL;
Container c1(pItem); // WRONG: pItem is not dynamically allocated; it is NULL
Item item;
Container c2(&item); // WRONG: &item does not point to a dynamically allocated heap
// object; the object is on stack;
所有権:オブジェクトへのポインタが挿入されると、そのオブジェクトはコンテナのプロパティになります。他の誰もそれを使用または変更することはできません。
オブジェクトがメモリ内に存在する場合、そのオブジェクトへのポインタまたは参照を持つオブジェクトまたは関数は、そのオブジェクトを変更する可能性があります(ポインタまたは参照が宣言されていない場合const
)。
Item *pItem = new Item(); // the function containing this code obviously has a pointer
// to the newly created item
Container c(pItem); // let the container c own this item
pItem->change(); // WRONG: attempt to modify an object owned by c
保存:ポインターがコンテナーから削除されるときは、ポインターをコンテナーに挿入するか、その指示対象を削除する必要があります。
つまり、コンテナが指すアイテムインスタンスを「所有」(上記とまったく同じ意味で定義)する必要がなくなった場合、コンテナは「所有権」を別のコンテナに譲渡するか、アイテムを削除する必要があります。クラスに対する次の変更は、Container
この動作を実装します。
class Container {
public:
removeItem() {
delete m_pItem; // deallocate the item instance owned by this container
// the item is no longer owned because it no longer exists
}
giveItemTo(const Container& other) {
other.m_pItem = m_pItem; // let the other container own this item instead
m_pItem = NULL; // the item is no longer owned by this container because the pointer is NULL
}
};