Objects Managing a Resource
What is a Resource Respects Release/Acquire protocol files (open/close) memory allocation (allocate/free) locks (acquire/release).
What is a Resource Objects when constructed, sometime acquire a resource. If designed carefully - acquire resource otherwise (when unavone oidable) will acquire several resources When an object is destructed, its resources must be released.
Construction of objects Allocating - Allocating enough memory to hold the object's state Initialization - Initializing the internal state of the object. This involves 2 sub-steps: Acquiring Resources - Acquiring the necessary resources which the object requires Consistent state - Making sure that the initial state of the object is valid according to the class invariants
Construction of objects RTE allocates the needed memory and calls the constructor of the class. constructor is different from normal method invocation object does not exist until the construction is finished. do not access this of object in the constructor. do not throw exceptions from the constructor…
destruction of the object when an object is constructed, resources are allocated: explicitly, by the object's constructor implicitly –memory allocated to hold the object's state resources should be deallocated. programmer's responsibility of releasing the resources acquired by a process
destruction of the object Releasing resources - releasing all of the resources acquired by the object during the object's lifetime and construction. Releasing memory - releasing all the memory allocated for the object
Who destructs what? destructing an object is shared between the RTE and the programmer: programmer releases resources acquired by constructor or during the life time RTE is responsible to release the memory allocated to hold the state of the object.
How to destruct? object is implicitly destructed if object is allocated on stack. when the program exits the scope of this object, the RTE will destruct the object. object allocated on the heap is destructed explicitly, by the programmer use delete operator on a pointer to the object.
Destruction order RTE calls a special function of the object- destructor. responsibility of the programmer to implement such a function, and release all resources acquired by the object during the object's lifetime. RTE releases memory used to hold the object's state from stack or heap
LifeCycle of an Object object is "born" after constructor successfully terminates. object "retired" after destructor successfully terminates. object is "alive“ following its construction and just before its destruction. object is valid only as long as the object is alive.
Shape Collection Example object that holds a collection of shapes. will not create new shapes on its own will receive previously constructed shapes to store build the class…
C++ interface Shape is an interface as all its functions are pure virtual [=0] in declaration Pure virtual are functions that the compiler enforce us to implement. An interface in C++ is implemented by using regular inheritance (C++ multiple inheritance) /** ... */ - special tokens recognized by doxygen for auto documentation
Remarks class Shape - is a forward declaration typedef is used to define new types Shapes is a type (just like int or any other class). typedef is common to replace long types to short std::vector<T> is a C++ template that holds a collection of type T.
Remarks add() is receiving const Shape* - Shapes is of type vector<Shape*> => our Shapes vector cannot directly hold pointers received by add function parameter is const and the vector is not const shapes are cloned and stored in collection cant just be referenced by the collection. fits well with collection description
Implementation
Remarks assert(Shape != 0) - as Add receives a pointer it must check for nullity. check man assert shapes_.size() must be const - why?
Memory leak class hold clones of Shapes - responsible for releasing clones upon object destruction. add appropriate dtor to ShapeCollection
Remarks Destructors are declared virtual… inheritance… If no good reason - declare each method as virtual. We added the *i=0 for educational reasons.
Remarks iterator is a pointer to an item of type T (here Shape*). Dereferencing iterator returns Shape* Dereferencing again to access a public method/member (**T)
Memory Addresses Aliasing
What is the problem? shapes passed to byVal is copied to s. no copy-ctor implementation – default default copy constructor performs a shallow copy of the object's state. shapes_ vector of shapes is copied. shapes on the heap pointed twice: from shapes, and from s!!!
What is the problem? byVal returns - destructor is called all the shapes of s1 are freed. shapes still holds the pointers to shape addresses in heap
Assignment (=) problem same problem arises with the assignment operator every Class is a type - supports assignment. given two ShapeCollections, s1 and s2: s1=s2 (s1=s1) exactly as you would do for an int or double.
Solution define copy and assignment behavior possible behaviors are: Do not allow one or both of them Explicitly implement behavior which is consistent with the class design
empty behavior should be implemented with every class you write. if later you need copy or assignment - move to second solution. How? declare copy constructor and assignment operator as private!
Copy copy-ctor. syntax: given a const reference to another object of the same type (which you would not want to change) copy its state to this object state
Class(const Class& other) = ctor - copy behavior
Class(const Class& other) = ctor - copy behavior
Shapes::const_iterator – an iterator to a const member of the Shapes vector.
Assignment special method of the object: operator= syntax: given another object of the same type (which you would not want to change) copy its state to this object's state return an L-Value - meaning return the value of the left object. make sure an object is not assigned to itself
need to define such behaviors on classes someone will extend class in the future. inheritance techniques to reduce the overhead.
Managing Heap resource on Stack Recall: compiler calls ctor, dtor of objects declared on the stack automatically - when the scope is entered and exited when object is copied, the compiler calls the copy constructor. same for the assignment.
Memory management class follow semantics of objects on the stack create generic class to hold object's pointer upon copy or assignment will not really copy the pointer but share it. count how many times the object is being referenced not delete it (when dtor is called) until the last reference is gone.
shared_ptr Boost - extension to the standard template library (STL), offering many advanced utilities
Remarks much shorter and cleaner. wrap the object of interest (shape*) - define a shared_ptr object on stack shared_ptr can then safely be given by value in most cases shared_ptr is exactly what we need, rather than the copy behavior
How does shared_ptr works? did not supply copy or assignment behavior: default–copy by val of all object's state. collection's state is shapes_ of type vector<shared_ptr<Shape>> copy constructor of vector is called vector holds a collection of objects - shared_ptr<Shape> (shShape)
How does shared_ptr works? Vector's copy-ctor copy by value - call shared_ptr copy-ctor – shares pointer to actual shape on the heap shared_ptr holds a pointer and manages the reference count of this pointer shared_ptr copy-ctor and =operator - copy pointer by value manage the reference counting, together with the destructor:
How does shared_ptr works? When shared_ptr<T> t1 is assigned to shared_ptr<T> t2 share two resources: the pointer managed by t1 is copied to t2, such that they now manage the same pointer. t1 and t2 share a counter to count how many shared_ptrs are managing the same pointer. copying the pointer and sharing the counter t2 increments the reference counter by one.
If t2 had a pointer prior to the copy, this pointer's reference count is first decreased by one. A similar scenario takes place upon copy construction.
When the dtor of shared_ptr is called - reference count is decreased. If count reaches zero, pointer managed by shared_ptr is deleted.
Exceptions During Construction problem may arise during ctor - lead to an exception being thrown exception during construction - object in an undetermined state. Re-implementing the new operator. Mastere C++
Exceptions During Construction Catching exceptions in ctor itself. two major problems: construction needs to fail - no way of signaling this other than throwing an exception ourselves and can not handle out of memory exception inside ctor - will be thrown before entering ctor (by the new operator).
Exceptions During Construction use the Factory design pattern; static method - in charge of initializing new objects return a pointer to a newly initialized object upon success or a null otherwise.
Factory Method any method whose main purpose is creation of objects. used to allow performing dangerous operation while creating an object example: memory allocation, accessing files, publishing the object address Factory Methods in Java for immutable objects. use of factory method has a wider scope
Arrays and Objects how to allocate arrays of primitive types in C++ each cell of the array is initialized using the default constructor. holds also for objects.
Each cell of the array is initialized twice! when the array is constructed, by using the default constructor using the assignment operator. total of 84 Shape objects created on stack