Saturday, April 11, 2015

C++ Dynamic Storage


Local variables are allocated in stack.  The new operator allocate storage in heap.  Unlike stack, heap storage persist beyond the current scope.  On the other hands, heap storage must be freed via the delete operator.

int* p = new(int);  // new return a reference of the newly allocated storage
*p = 100;

When an object contains pointer to heap storage, the default destructor will lead to memory lead as the pointer will be released but not the area it points to.  Therefore, a customized destructor must be written and it should use delete to remove the dynamic area allocated.

A copy constructor has the same name of the class and accept a object of the same class.  For example,

Class C1 {
...

string p*

C1(const C1 &Ca) {
    p = new string(*(ca.p));
    }
...
}

The copy constructor is use to copy a object to another object of the same class.  The default copy constructor does a shallow copy.  In other words, if the class contains a pointer to a dynamically allocated area, the copy will be copy to the target object but the dynamic area will not be duplicated.  Both objects will point to the same area.  When one of the object is released, the destructor may release the dynamic area.  The remaining object will then end up containing a dangling pointer.

C++ friend functions


Friend functions are defined within a class that enable these functions outside the class to access the function and data within the object.  The function can be a C++ function or a operator-overload function

Class C {
    friend void fn (...)  // a normal function
    friend a& operator<<(..._  // operator overloading of <<
    .... // normal class definition
}

Friend functions are declared outside of the class  

C Array


The name of an array is a constant pointer to the first element of the array.  We can pass an array to the function of the equivalent signature

int fn(int* const x)

int a[5] = [100, 200, 300, 400, 500];
int b
b = fn(a);

Because array name is a pointer, it can be returned by a function as such (beware of out-of-scope issue).

Pass By Pointer in C++


Passing argument to a function can be more efficient when using the pass-by-reference method, especially when the argument size is huge.

int fn(int& x, int& y)

The same level of efficiency can also be achieved using constant pointers.  You can change the value pointed to but not the pointer itself, similar to using references

int fn(int* const p, int* const q)

Similar to returning a reference in a function, be careful not to returning a pointer to an out-of-scope object. Commonly, the return pointer points to an area in heap allocated by the new operator.  Likewise, using a pointer to receive a returning pointer is efficient as it will not involve any copying of the object content.  Using a variable to receive a returning pointer will end up making a copy of the object the pointer points to.

C++ Pointers


Pointer contains address of another variable or object.  To point to an existing variable, assign the point using the address operator (&)

int a
int* b = &a

To access the variable pointed by a pointer, use the dereference operator (*)

int c = *b

A constant pointer cannot change to point to another variable

int* const b = &a
b = &c // generates error

A pointer to a constant cannot change the value of the variable the pointer points to

const int* b
*b = c // generates error

a constant pointer to a constant is most restrictive
const int* const b

C++ Reference


A reference is an alias for another variable.  It is declared using the & operator

int a = 100;
int& b = a

A reference must be initialized when it is declare or results in compilation error.

Reference can be used in place of the variable (as it is just like have another name for the same variable)

a += 1 or b +=1 yields the same result

To pass by reference in a function fn is efficient if the parameter size is large

int fn(int& x, int& y)
int i, j, k

i = fn(j, k)

fn can change the value of j and k in its code.  To prevent fn changing the arguments, declare the funciton using constant reference

int fn(const int& x, const int& y)

When a function returns a reference (e.g. int& fn(...)), it must make sure that the deference is not on a local variable as the memory storage will disappear when the fn goes out of scope.  It must return either a static variable or a reference to a parameter.  The calling program can assign the return reference value to another reference variable.  In this case, the return object is not copied

int& a = fn(...)  // no copy of content

If the calling program uses a variable to receive the return value, the content of the object will be copied

int a = fn (..) // content copy