At-most-once: A pointer to any specific object can exist in at most one container object at any point in time.
Existence: An object must be dynamically allocated before a pointer to it is inserted.
Ownership: Once a pointer to an object is inserted, that objects becomes property of the container. No one else may use or modify it in any way.
Conservation: When a pointer is removed from a container, either the pointer must be inserted into some container, or its referent must be deleted.
These are the respective definitions I've been given. I'm having trouble understanding the various terminology used in each of them, and I was hoping someone here could explain exactly what each one means and how they're used to ensure good programming practice.
As an example, assume you have the following class definitions:
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
};
At-most-once: A pointer to any specific object can exist in at most one container object at any point in time.
Having two instances of Container with a pointer to the same instance of Item would violate this:
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
Existence: An object must be dynamically allocated before a pointer to it is inserted.
Dynamically allocating an object generally means creating a new instance of an object with the operator new, which returns a pointer to the newly created object allocated on heap memory (as opposed to stack). Two examples of a violation of this are:
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;
Ownership: Once a pointer to an object is inserted, that objects becomes property of the container. No one else may use or modify it in any way.
When an object exists in memory, any object or function that has a pointer or reference to the object could potentially modify it (unless the pointer or reference is declared 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
Conservation: When a pointer is removed from a container, either the pointer must be inserted into some container, or its referent must be deleted.
This means that when the container no longer wants to "own" (defined in exactly the same sense as above) the item instance it points to, it must either transfer "ownership" to another container, or delete the item. The following modification to the Container class implements this behavior:
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
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With