Monday, 2 April 2012

Special class methods for object creation, assignment and destruction

Object in C++ can be created as a:
  • global (on the stack)
  • local (on the stack)
  • dynamic (on the heap)
  • temporary object by explicitly calling its constructor (e.g. passing temporary object to function)
  • temporary object when created implicitly by compiler (e.g. when passing object to function by value)
  • data member of another class (created when another class is created)
  • base class sub-object of the instance of the inherited class (base part)

There are three types of C++ class constructor:
  • default constructor - the one that can be called with no parameters (it does not have any parameters or all parameters have default values); can be implicitly (compiler-) or user-defined; if it is not user-defined and class does not contain const or reference members, it will be created by compiler and will be public
  • non-default constructor - must be called with at least one argument; 
  • copy constructor - called when one object is created from another (already created);  has a single parameter of type A&, const A&, volatile A&, or const volatile A&; can be implicitly (compiler-) or user-defined; if it is not user-defined, it will be created by compiler and will be public; implicit copy-constructor performs shallow copy (memberwise copy); user-defined copy constructor can have additional parameters but they all must have default values

Assignment operator (operator=) assigns value of one (already created) object to another (already created object). If the left-hand side object is being created from the already existing right-hand side object then a copy-constructor will be called (not assignment operator!). operator= can be implicitly (compiler-) or user-defined; if it is not user-defined, it will be created by compiler and will be public; implicit assignment operator performs shallow copy (memberwise copy).

Destructor is another special function that is generated by compiler if it is not provided by the user. When objects created on the stack go out of the scope, their destructor will be called automatically. Destructor must be explicitly called for dynamic objects otherwise we would have memory leaks.

The following example demonstrates relying on compiler-generated copy-constructor and assignment operator:



Output:
goo(): n = 1
c0:
C::C(): n_ = 0
c1:
C::C(): n_ = 1
c2:
c3:
c4:
C::C(): n_ = 0
c5:
C::C(): n_ = 5
C::~C(): n_ = 5
C::~C(): n_ = 1
C::~C(): n_ = 1
C::~C(): n_ = 1
C::~C(): n_ = 1
C::~C(): n_ = 0

The following example demonstrates program output when using user-defined copy-constructor and assignment operator:



Output:
goo(): n = 1
c0:
C::C(): n_ = 0
c1:
C::C(): n_ = 1
c2:
C::C(const C&): rhs.n_ = 1
c3:
C::C(const C&): rhs.n_ = 1
c4:
C::C(): n_ = 0
C::operator=(const C&): rhs.n_ = 1
c5:
C::C(): n_ = 5
C::~C(): n_ = 5
C::~C(): n_ = 1
C::~C(): n_ = 1
C::~C(): n_ = 1
C::~C(): n_ = 1
C::~C(): n_ = 0

One interesting thing happened in line (4) - we would expect copy-constructor to be called here but normal constructor is called instead. This is the consequence of compiler's optimization called Copy elision. When temporary object is meant to be created only to initialize object that is to be constructed, compiler only constructs target object, passing arguments of temporary object constructor to it.

If we want to make our class non-copiable and non-assignable we just have to declare copy-constructor and assignment operator as private, without providing definitions! Our declaration tells compiler not to generate these methods so there will be no implicit definitions. If we call them through public access - the code won't compile. If we try to call them inside class method, the code will compile but linker will complain as it could not find definitions for these two methods.



Compiler output:
(1) error C2248: 'C::C' : cannot access private member declared in class 'C'
(2) error C2248: 'C::C' : cannot access private member declared in class 'C'
(3) error C2248: 'C::C' : cannot access private member declared in class 'C'
(4) error C2248: 'C::C' : cannot access private member declared in class 'C'

Links and references:

Constructors (C++)
Constructor (object-oriented programming) (Wikipedia)
Copy constructor (Wikipedia)
Assignment operator (C++) (Wikipedia)
The Anatomy of the Assignment Operator by Richard Gillam
Destructor (Wikipedia)
Constructors (by Danny Kalev)
Why is the copy constructor not called? (SO)

1 comment:

micheal pan said...

BE SMART AND BECOME RICH IN LESS THAN 3DAYS....It all depends on how fast 
you can be to get the new PROGRAMMED blank ATM card that is capable of
hacking into any ATM machine,anywhere in the world. I got to know about 
this BLANK ATM CARD when I was searching for job online about a month 
ago..It has really changed my life for good and now I can say I'm rich and 
I can never be poor again. The least money I get in a day with it is about 
$50,000.(fifty thousand USD) Every now and then I keeping pumping money 
into my account. Though is illegal,there is no risk of being caught 
,because it has been programmed in such a way that it is not traceable,it 
also has a technique that makes it impossible for the CCTVs to detect 
you..For details on how to get yours today, email the hackers on : (
atmmachinehackers1@gmail.com ). Tell your 
loved once too, and start to live large. That's the simple testimony of how 
my life changed for good...Love you all ...the email address again is ;
atmmachinehackers1@gmail.com