©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying,...

65
©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management

Transcript of ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying,...

Page 1: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

C++ Certificate ProgramC++ Intermediate

Object Creation, Copying, Lifetime Management

Page 2: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Constructors and Destructors (Review!)

• Essential part of Object-Oriented Languages• Enforces initialization and cleanup.

– These represent a large segment of errors in C • Allow object invariance to be implemented -- state of an

object can be known once constructed (no ‘intermediate’ state)

• Use of any non-trivial type assumes some initialization be performed prior to first use– In C, this is traditionally via an init() or initialize() routine

• In C++ this initialization is paramount, never left to class user / client to determine if and when

Page 3: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Ctor and Dtor DetailsConstructors and destructors are similar to

other methods except that they:

• Automatically call base ctors and dtors

• Automatically call member data ctors and dtors

• Have no return type

• Destructors take no arguments

Page 4: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Memory Allocation

• Constructor does not allocate memory for an object– For automatic objects the compiler allocates

memory– For free store objects, memory is allocated by

‘new’ operator implementation

Page 5: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Memory Deallocation

• Destructors do not deallocate memory

• Memory deallocation is responsibility of ‘delete’ operator or the compiler

Page 6: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Automatic Objects

• Constructors and destructors are automatically called when objects are created

• When execution leaves object scope, object is destroyed / destructor is automatically called

Page 7: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Example

class X {…};

void f() {

X x; // automatically calls constructor

//object is destroyed here when going out of

// scope and destructor invoked

}

Page 8: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Free-Store Objects

• Dynamically created objects allocated via call to operator new

• Constructor called via operator new

• Objects created dynamically must be explicitly destroyed via operator delete

Page 9: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Example

class X {…};

void f() {X *x = new X; // constructor invoked after

// new()delete x; // destructor invoked via

// delete}

Page 10: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Compiler Generated Default Ctor

• Class can have many overloaded constructors but only one destructor– Obvious as destructors take no parameters

• If no constructors declared for a class, compiler will generate a default ctor (no parameters), performs default initialization of attributes– Recursively invokes base default ctor, member

data default ctors (or nothing, if built-in type)

Page 11: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Implicit Constructor Invocation

• C++ provides a simplified form of calling a constructor with a single parameter (masked via ‘=‘ symbol)

• At first glance invokes assignment operator, but instead invokes matching constructor

Page 12: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Exampleclass X {public:

X (X const &); // copy ctorX (int);X (std::string const &);X (double);

private:// disable copy assignment from client useX& operator= (X const &);

};

int f() {X x1 = 5; // X(int)X x = x1; // X(X const &)X x3 = 5.0; // X(double);

}

Page 13: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Explicit Constructor Motivation

• Sometimes semantically confusing

class MyVector {Public:

MyVector (int size = 0);};

int foo() {MyVector states = 50; // just what does

// this mean?}

Page 14: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Example

• Sometimes incorrect logic

void v (MyVector<int> const& vec) {if (vec(10) == 20) { // ack! … will compile// …}

}// correct logic was meant to be// if (vec[10] == 20)

• What does the incorrect line actually do?

Page 15: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Explicit Semantics

• Explicit keyword disallows implicit conversions for single argument constructors

• In some cases failing to use explicit keyword can results in unintended errors

Page 16: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Explicit Keyword Added

class MyVector {Public:

explicit MyVector (int size = 0);};

void v (MyVector<int> const& vec) {if (vec(10) == 20) { // now syntax error// …if (vec(10) == vec(20)) {// compiles due to explicit construction,// although questionable logic

}

Page 17: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Explicit Constructors

• Explicit constructors still allow construction with appropriate type, but disallow implicit conversion as part of the construction

• General rule is to make single parameter constructors explicit unless implicit conversion desired functionality

Page 18: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Avoiding Redundancy in Constructors

• Often need to declare default constructors– Appropriate design for class– Certain uses of STL require it (primarily in container ctors that

construct with a default value, or in resizing to a larger size)• Sometimes difference between default and non-default

constructor is only in values assigned to members– Almost always true for constructors that just perform raw

initialization• Instead of two constructors, use default values for all

arguments– Still equivalent to a default constructor

Page 19: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Example, Redundant Ctors

class X {public:

X() :ival(0), dval(0.0) {}X(int a = 0, double d = 0.0)

: ival(a), dval(d) {}private:

int ival;double dval;

};

int f() {X x1; // X() : ival = 0, dval = 0.0X x2(5); // illegal call! Both or neitherX x3(5,10.5); // X(int,double) : ival = 5, dval = 10.5

}

Page 20: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Example, No Redundant Ctorsclass X {public:

X(int a = 0, double d = 0.0): ival(a), dval(d) {}

private:int ival;double dval;

};

int f() {X x1; // ival = 0, dval = 0.0X x2(5); // ival = 5, dval = 0.0X x3(5,10.5); // ival = 5, dval = 10.5

}

Page 21: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Initializer Lists

• Code within ctor body must be able to make certain assumptions

• Should have known, sane state on entering ctor body: should be able to assume that base data and all members (attributes) are initialized for ctor body

• If these assumptions couldn’t be made, semantics of ctor bodies would be complex and error-prone

Page 22: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Guaranteed Initialization• C++ ensures all initialization is performed

prior to entering the constructor body

• Problem: How to have control over construction / initialization of base and member data?

Page 23: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Initializer Lists• C++ provides initializer lists

• These effectively provide a "pre-body" with special syntax

• Initializer lists only used for initialization of base and member data, in constructors

• Exception safety in initialization blocks is achieved via function try blocks

Page 24: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Why Use Initialization Lists?

• Two primary reasons:– In certain cases, no other syntax will allow

initialization– Efficiency

Page 25: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Required Uses

• Base object construction: If base type does not provide default constructor, initializer list must be used to provide initialization values

• Member data construction: Similar to base object construction (if default ctor not provided in member’s class, must use initializer list)

• Initialization of constant members: Must be initialized through initializer list

• Initialization of references: Member references must be initialized through initializer list

Page 26: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Efficiency

• Can be inefficient (or awkward) to default construct member data, then assign to it (in ctor body)– Just as in any other code

• Meaningful constructors should be used over default construction followed by assignment

Page 27: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

More on Initializer Lists

• Default construction in the initializer list provided through empty parentheses (built-in types have language specified default values, typically some form of 0)

• Arrays cannot be initialized through init lists, populating array must be performed in constructor body (or elsewhere)

Page 28: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Exampleclass Engine {public:

explicit Engine (std::string const& description = "",int const horsepower = 200)

: mDescription(description), mHorsepower(horsepower) {}

private:std::string mDescription;int mHorsepower;

};

class Suspension {public:

explicit Suspension (bool sportTuned = false): mSportTuned(sportTuned) {}

private:bool mSportTuned;

};

Page 29: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Exampleclass Vehicle {public:

Vehicle (int wheels): mSusp(), mEngine(), mNumWheels(wheels) {}

private:Suspension mSusp;Engine mEngine;int const mNumWheels_;

};

class Sedan : public Vehicle public:

Sedan () : Vehicle (4) {}// …

};

Page 30: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Recommendation

• In every constructor, construct/initialize all base objects and every member in the initializer list; use empty parentheses syntax for default construction

• Specify members in initializer list in same order as are declared in the class (class members are initialized in the order they are declared)

Page 31: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Deferred Construction and Pre-destruction

• Constructors and destructors are an integral part of OO languages

• However, some dismiss them as ‘syntactic sugar’• They instead employ a C idiom, which in the OO

world is referred to as deferred construction:– No meaningful ctors, instead performing

“initialization” at a later time– Classic C init() or initialize() methods …

Page 32: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Exampleclass Y {public:

Y() : mInt(0), mDouble(0.0), mZptr(0) {}void init (int i, double d) {

mInt = i; mDouble = d; mZptr = new Z;

}void deinit() {

delete mZptr;mZptr = 0;

}private:

int mInt;double const mDouble;Z* mZptr;

};

Page 33: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Design Consequences

• Without constructors cannot use constants or references in the class (forced to use non-const pointers instead of references)

• Invariance is thrown out the window, resulting in poor design

• Pre-destruction (through deinit()) complicates object usage, potentially leaving it in an unstable state

Page 34: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

More Advice

• Constructors, destructors, and initializer lists are not syntactic sugar – are essential features of the C++ language

• Constructors are present in almost all OO languages - well defined and well tested in their utility

• Not using them will result in overly complicated object states and potentially complex, inefficient, and error-prone code

Page 35: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Object Integrity• C++ (and most OO languages) allow a designer to

guarantee the consistency and integrity of an object throughout its lifetime (outside of purposeful attempts to corrupt an object)– Made possible through construction, destruction, and

encapsulation semantics

• Deferred construction and "pre-destruction" prevent or complicate the designer's ability to guarantee the consistency and integrity of an object

Page 36: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Constructing Arrays

• Array usage can be difficult for a number of reasons - STL containers contain useful functionality not present in arrays

• Recall that arrays of objects can be dynamically allocated by using the new[] operator

Employee* employees = new Employee [100];

// …

delete[] employees;

// delete employees; would be error –

// what could happen and why?

Page 37: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Constructors, Destructors and Arrays

• Review: default ctor called for each element of the array when new’ed

• In the example, 100 Employee ctors will be called when allocating the employees array – Ctors will be called regardless of whether all objects

will be used• Delete[] will invoke 100 destructors• Less than ideal for some purposes

Page 38: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

What About Expansion?

• C++ provides only one means of "growing" a dynamically allocated array: realloc()

• Realloc is part of the C standard library and not designed to play nicely with the object-oriented world of C++ - specifically ctors and dtors are not invoked

Page 39: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Example, Undesirable Approach

Employee* moreEmployees = new Employee [200];

for (int i = 0; i < 100; ++i) {moreEmployees [i] = employees [i];

}

delete[] employees;employees = moreEmployees;

Page 40: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Behavior• Will invoke 200 default constructors, 100

assignment operators and 100 destructors

• Expensive performance-wise, error-prone, hard to maintain

• Usually not acceptable to a developer - what can be done?

Page 41: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Another Approach

• Better performance: allocate an array of pointers to objects

• Pointers can be initialized to 0 until the objects are allocated

• Allows construction only as needed – Default constructors not required - can initialize

objects as desired

Page 42: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

ExampleEmployee** moreEmployees = new Employee* [200];

// copy pointers from employees array – could// be STL algorithm or using memcpy

// set remaining contents of new array to 0,// could STL algorithm or memset

delete[] employees;employees = moreEmployees;

Page 43: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Comparison

• Runs far faster than original version

• All extra work related to calling assignment operators and extra ctors and dtors has been eliminated– However, code is more complex, and

maintenance issues may start to arise

• A more modern approach, using the boost library for its handle classes, might be:

Page 44: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Example Using Boost Ptr Class#include <vector>#include <boost/smart_ptr.hpp> // smart pointer classes

int main () {

typedef boost::shared_ptr<Employee> HEmployee; std::vector<HEmployee> employees;

employees.reserve(100); // space pre-allocation // Allocate each object individually (with appropriate // constructor), add to the end of the container employees.push_back(HEmployee(new Employee(…))); //… add other Employees as needed

// increase capacity to 200, preserving originals employees.reserve(200);

// All destruction and cleanup taken care of by // the container and handles return 0;}

Page 45: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Consequences• Using a standard library container and a handle

simplifies the code (especially memory management logic)

• In last two examples, the array or container is storing pointers to Employee objects, rather than Employee objects themselves

• Can provide substantial savings in object memory usage and processing time (because object copying is avoided)

• Using pointers or handles to objects can simplify object association and object uniqueness issues

Page 46: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Exception Safety in Constructors

• Two kinds of behaviors should be associated with properly written code that uses exceptions

• Code should be exception-safe and exception-neutral

• For the following definitions, exception could be thrown directly by method, or indirectly through a function called by the method

Page 47: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Exception-Safe

• Method is defined to be exception-safe if, upon throwing an exception:– no resources are leaked– the object or system state remains valid

• This guarantee sometimes referred to as the basic or weak exception-safety guarantee

Page 48: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Exception-Neutral

• A method is defined to be exception-neutral (I.e. provides the strong exception safety guarantee) if the following condition holds true:– If the method terminates by propagating an

exception, any changes to the state of the application are rolled back or uncommitted

Page 49: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Example From Exceptional C++

template <typename Element> class Stack {public:

Stack();~Stack();// …

private:Element* vector_;size_t size_;size_t used_;

};

template <typename Element>Stack<Element>::Stack() : vector(0), size(10), used(0) {

vector = new Element [size];}

Page 50: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Class Functionality

• Clearly Stack is a container, required to manage dynamic memory resources

• Important to ensure no leaks, even when exceptions thrown by Element type operations (e.g. in Element default constructor) or standard memory allocations

Page 51: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Is This Ctor Exception-Safe and Exception-Neutral?

• Nothing in the initializer list can throw• Statement in ctor body first tries to call operator new[], either default version or one provided by Element, then tries to call Element default constructor ‘size’ times

• Two operations might throw exceptions: – Memory allocation itself, thowing std::bad_alloc– Element default constructor (could throw anything) –

language guarantees any constructed objects are destroyed (invoking dtor), allocated memory is returned via operator delete[]

Page 52: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Is Default Constructor Robust?

• Yes, for the following reasons:– No resource (memory in this case) leaks– Stack will be in a consistent state whether or

not any part of the initialization throws– Exception-neutral – any thrown exception is

correctly propagated up to caller– “Proto-object” never became a completely

constructed object

Page 53: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Is Destructor Robust?

template <typename Element>

Stack<Element>::~Stack() {delete[] vector_; // can't throw

}

• Yes – delete[]’ing the array invokes Element destructor for each object in the array, then calls operator delete to deallocate heap memory (which will never throw)

• Stack requires Element dtor to never throw

Page 54: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Is Push Robust?

template <typename Element>

void Stack<Element>::push(Element const& val) {

// implementation of push method

}

• Traditional implementations are not exception safe• Exercise – design an implementation that is

exception-safe (hint – take advantage of language construction guarantees)

Page 55: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

The Resource Acquisition Is Initialization Technique (RAII)

• Exploit constructor and destructor behavior via object scope

• Guarantee resource cleanup using language scoping rules (dtor of local / stack objects will always be invoked when the object goes out of scope)

Page 56: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Exampleclass InvocationDocumenter {public:

InvocationDocumenter (std::string const& func) : mFunc(func) {std::cout << "Entering " << mFunc << std::endl;

}~InvocationDocumenter () {

std::cout << "Leaving " << mFunc << std::endl;}

private:std::string const mFunc;

;

// example usagevoid Cactus::sitStill () {

InvocationDocumenter invocation ("Cactus::sitStill");// do lots of stuff: return anywhere, throw an exception,// do whatever you want, you can't stop this documenter// from printing when you leave the function, short of// crashing the application

}

Page 57: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

RAII Usage• Use the technique whenever something should

automatically happen at end of a given scope, for example:– opening/closing a file no matter how a given method completes or

throws

– releasing any resource, such as a Windows HANDLE or a BSD Socket

– documenting the lifetimes of methods and objects

– performing timing of a given section of code

– documenting lifetime of a dynamically loaded library (DLL/shared lib) via a global or anonymously namespaced RAII object

Page 58: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Handles

• Presents an interface for another class whose representation should be hidden from user

• Used in place of the true, underlying object

• Operations are performed on handle class, which forwards them on to internal object

Page 59: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Handle Classes

• Representation can vary independently since work done through handle interface

• Frequently interfaces forward via the pointer-to (operator->) and dereference (unary operator*) operators

• A Decorator could be considered a handle class - provides same interface as component it decorates, forwards requests through to actual component

• Not just an OO concept – MS Windows uses handles to decouple application from actual representation of various OS-defined "objects,” such as windows, hardware devices, and fonts

Page 60: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Simple Example

class HCar {public:

HCar (Car* representation): mCarRep(representation) {}

Car* operator-> () {return mCarRep;

}private:

Car* MCarRep;};

HCar car (new Civic());car->accelerate();

Page 61: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

auto_ptr<T>

• Std library facility for safer handling of pointers

• Uses RAII to accomplish its main goal: automatic pointer deletion at the end of its scope

Page 62: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Example

#include <memory>

std::auto_ptr<Car> civic (new Civic());

// the following line changes the owner

// of the pointer to primary car, which

// invalidates civic

std::auto_ptr<Car> primaryCar (civic);

primaryCar->accelerate();

// do not dereference civic at this point

Page 63: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

auto_ptr<T> Semantics

• 1998 C++ standard defines as follows:– An auto_ptr owns the object it holds a pointer to. Copying an

auto_ptr copies the pointer and transfers ownership to the destination. If more than one auto_ptr owns the same object at the same time the behaviour of the program is undefined.

• Strict ownership policy is used for simplicity and storage efficiency

• Since copy construction and assignment do not follow the usual logic (source and destination are “equivalent”), auto_ptr cannot be used in containers or arrays

Page 64: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Candidates

• Short-lived, dynamically allocated objects• “Source / Sink” functions• Objects created dynamically and need to be

destroyed only in the case of an exception• Objects with complex lifetimes, or with

sharing needs (e.g. passed throughout an application) require more robust handles, such as boost::shared_ptr

Page 65: ©Fraser Hutchinson & Cliff Green C++ Certificate Program C++ Intermediate Object Creation, Copying, Lifetime Management.

©Fraser Hutchinson & Cliff Green

Constraints

• auto_ptr cannot handle arrays allocated with new[] – always performs single object delete, cannot deduce array versus single object

• Important to note with almost all pointer handle implementations