Implicitly defined members of a class in C++

What members of a class are implicitly defined?

There are quite a few things that you get when you make a class (if they aren't explicitly defined). The important thing to note is that they are not actually created/written by the compiler unless it's sure that you need them. Let's go ahead with an example empty class named 'MyClass'. Below are those members alongwith the constructs that force them into existence:
  • Default (zero-argument) constructor
    Whenever an object of the class is created unless there are any parameterized constructors defined.

    MyClass ObjectOfMyClass;   // Object creation
  • Copy constructor
    Whenever copy construction is initiated.

    MyClass ObjectOfMyClass;
    MyClass AnotherObjectOfMyClass = ObjectOfMyClass;   // Copy construction
  • Assignment operator
    Whenever the assignment operator '=' is used with objects of the class.
    MyClass ObjectOfMyClass;
    MyClass AnotherObjectOfMyClass;
    // some more code manipulating the objects
    ObjectOfMyClass = AnotherObjectOfMyClass;   // Assignment  operator
  • Destructor
    If there is an explicitly/implicitly defined constructor (nothing to do with the keyword 'explicit') and an object is created. That would mean if you went through some code as stated in the first point, a destructor would be generated and called whenever the object is destroyed. 


  • A pair of 'address-of' operators
    There are two versions: a 'const' one and a 'non-const' one. When the '&' ('address-of') operator is used on a const object, first version is generated and the later one associates itself with a non-const object with similar usage.

    MyClass ObjectOfMyClass;
    const MyClass ConstObjectOfMyClass;
    MyClass* ptr = &ObjectOfMyClass;   // Causes non-const version creation
    ptr = &ConstObjectOfMyClass;   // Causes const version creation
If there are all the above mentioned operations in a program, the empty 'MyClass' would be somewhat equivalent to:
class MyClass
{
  public:
    MyClass() {}
    MyClass(const MyClass& rhs) {}
    MyClass& operator=(const MyClass& rhs) {}
    MyClass* operator&() { return this; }
    const MyClass* operator&() const { return this; }
    ~MyClass() {}
};
These will appear in all cases where you don't explicitly define them but are forcing their calls in the above mentioned ways. So just be aware.
Note : If you define the copy constructor for your class, you don't get the default constructor.

Source:
http://www.codeguru.com/forum/showthread.php?t=356418

How a C/C++ Program Works


A program written in C/C++, is compiled into a binary or executable file and stored on the hard disk. To do anything useful this executable file has to be loaded into a process by the operating system from where the microprocessor can execute it.
Once an executable has been loaded into a process, the processor will start executing its code from a well known entry point usually written as the one and only main function in our program. The process is given resources by the operating system which among other things consists of:

Stack Memory - To hold auto variables, function parameters and return values. When your code invokes a function, its parameters are pushed on to the stack, its return value is implicitly pushed on to the stack and its variables are also pushed on to the stack. The called function is now logically on top of the stack. When the function ends its local variables are popped of the stack and hence local variables are also called auto variable. The size of stack memory is limited and to hold larger collections of data, we use the heap.

Heap Memory - This memory can be allocated on demandfrom our program and used to the extent of RAM limit available in the system. A reference of the address location of memory allocated to our program has to be held and later passed on explicitly for deallocation to the runtime system. This is done through a mechanism called pointers.

File Handles - This memory is used to hold file handles of open files in our program in a file handle table.
Variables in our program may be classified as data variables and pointers. Data variables are created on the stack and their address is represented in our program as a variable name. The data is stored starting from the first byte of the location. The range of bytes used to store the data depends on the type of the variable.

Pointer variables are also created on the stack but they can only hold addresses of other variables which may be on the stack or on the heap. The data held at the location indicated by the pointer can be indirectly accessed using the pointer this is known as de-referencing the pointer.
Memory can be dynamically allocated to a pointer on the heap. The size of memory allocated depends on the data type of the pointer. the pointer will hold the address of the location as long as we require. When we finish with the memory allocated, we have to explicitly deallocate the pointer which results in the pointer holding an address at which our program no longer controls memory. We have to deinitialize the pointer by setting its contents to zero or NULL.

This has been the trend with most C/C++ runtimes so far, but it may change given that now we are at the threshold of 64 bit computing and embedded computing on more powerful devices.

Source:

Size of a Class Object

Determining the size of a class object
There are many factors that decide the size of an object of a class in C++:
  1. Size of all non-static data members
  2. Order of data members
  3. Byte alignment or byte padding
  4. Size of its immediate base class
  5. The existence of virtual function(s) (Dynamic polymorphism using virtual functions).
  6. Compiler being used
  7. Mode of inheritance (virtual inheritance)
Size of all non-static data members

Only non-static data members will be counted for calculating sizeof class/object.
class A {
private:
        float iMem1;
        const int iMem2;
        static int iMem3;
        char iMem4;
};
For an object of class A, the size will be the size of float iMem1 + size of int iMem2 + size of char iMem4. Static members are really not part of the class object. They won't be included in object's layout. <2>Order of data members The order in which one specifies data members also alters the size of the class.
class C {
        char c;
        int int1;
        int int2;
        int i;
        long l;
        short s;
};
The size of this class is 24 bytes. Even though char c will consume only 1 byte, 4 bytes will be allocated for it, and the remaining 3 bytes will be wasted (holes). This is because the next member is an int, which takes 4 bytes. If we don't go to the next (4th) byte for storing this integer member, the memory access/modify cycle for this integer will be 2 read cycles. So the compiler will do this for us, unless we specify some byte padding/packing.

If I re-write the above class in different order, keeping all my data members like below:
class C {
        int int1;
        int int2;
        int i;
        long l;
        short s;
        char c;
};
Now the size of this class is 20 bytes.

In this case, it is storing c, the char, in one of the slots in the hole in the extra four bytes. 

Byte alignment or byte padding
As mentioned above, if we specify 1 byte alignment, the size of the class above (class C) will be 19 in both cases. 

Size of its immediate base class
The size of a class also includes size of its immediate base class.

Let's take an example:
Class B {
...
        int iMem1;
        int iMem2;
}

Class D: public B {
...
        int iMem;
}
In this case, sizeof(D) is will also include the size of B. So it will be 12 bytes.

The existence of virtual function(s)
Existence of virtual function(s) will add 4 bytes of virtual table pointer in the class, which will be added to size of class. Again, in this case, if the base class of the class already has virtual function(s) either directly or through its base class, then this additional virtual function won't add anything to the size of the class. Virtual table pointer will be common across the class hierarchy. That is
class Base {
public:
...
        virtual void SomeFunction(...);
private:
        int iAMem
};

class Derived : public Base {
...
        virtual void SomeOtherFunction(...);
private:
        int iBMem
};
In the example above, sizeof(Base) will be 8 bytes--that is sizeof(int iAMem) + sizeof(vptr). sizeof(Derived) will be 12 bytes, that is sizeof(int iBMem) + sizeof(Derived). Notice that the existence of virtual functions in class Derived won't add anything more. Now Derived will set the vptr to its own virtual function table. 

Compiler being used
In some scenarios, the size of a class object can be compiler specific. Let's take one example:
class BaseClass {
        int a;
        char c;
};

class DerivedClass : public BaseClass {
        char d;
        int i;
};
If compiled with the Microsoft C++ compiler, the size of DerivedClass is 16 bytes. If compiled with gcc (either c++ or g++), size of DerivedClass is 12 bytes.

The reason for sizeof(DerivedClass) being 16 bytes in MC++ is that it starts each class with a 4 byte aligned address so that accessing the member of that class will be easy (again, the memory read/write cycle). 

Mode of inheritance (virtual inheritance)
In C++, sometimes we have to use virtual inheritance for some reasons. (One classic example is the implementation of final class in C++.) When we use virtual inheritance, there will be the overhead of 4 bytes for a virtual base class pointer in that class.
class ABase{
        int iMem;
};

class BBase : public virtual ABase {
        int iMem;
};

class CBase : public virtual ABase {
        int iMem;
};

class ABCDerived : public BBase, public CBase {
        int iMem;
};
And if you check the size of these classes, it will be:
  • Size of ABase : 4
  • Size of BBase : 12
  • Size of CBase : 12
  • Size of ABCDerived : 24
Because BBase and CBase are derived from ABase virtually, they will also have an virtual base pointer. So, 4 bytes will be added to the size of the class (BBase and CBase). That is sizeof ABase + size of int + sizeof Virtual Base pointer.

Size of ABCDerived will be 24 (not 28 = sizeof (BBase + CBase + int member)) because it will maintain only one Virtual Base pointer (Same way of maintaining virtual table pointer). 

Source:


Overloading new and delete operators in c++

The new and delete operators can also be overloaded like other operators in C++. There are interesting possibilities of doing the same. However, some care should be taken regarding the parameters to accept, value to return and place to declare. This article covers all possible forms of overloading these operators and their uses.
 

In C++, the new operator is the recommended way of allocating memory, rather than using the malloc() of C, which is nevertheless available. The reason for preferring new over malloc is that new will also result in the constructor (wherever applicable) being called, but malloc does not. This is a very big point in C++; so big that I will devote an entire article for this later on. But for now, let us see why and how to overload new.

Why overload new and delete?
1.    To take charge or control over how to allocate memory
2.    To aid in debugging; keep track of memory allocation and deallocation in the program
3.    To do some other operation apart from allocating memory at the time of memory allocation/deallocation
Given below is a simple sample demonstrating overloaded new and delete:
void* operator new(size_t num){    return malloc(num);}
void operator delete(void *ptr){    free(ptr);}
Observe the following:
1.    The overloaded new operator receives a parameter num of type size_t. This is the number of bytes of memory to be allocated. The compiler calculates and sends this to us!
2.    The return type of the overloaded new must be void*. It is expected to return a pointer to the beginning of the block of memory allocated. Note that after our overloaded new returns, the compiler then automatically calls the constructor also as applicable.
3.    The overloaded delete operator receives a parameter ptr of type void*. This is the pointer the user is trying to delete.
4.    The overloaded delete operator should not return anything.
5.    In this sample implementation, since the focus is only on showing how to overload, we have done the memory allocation and deallocation using malloc() and free() functions. In real life situations, we would prefer to do something more than this!


Deleting an array of objects is not the same as deleting an object, i.e. delete[] ptr; and delete ptr; are totally different and involve different operators! In case you are interested in overloading delete for an array, use the following:
void operator delete[](void *ptr){    free(ptr);}
The overloaded new operator can accept additional arguments as required! Yes, it is possible to have multiple overloaded new operators in the same program! Consider the following example:
void* operator new(size_t num, char x)
{
    void *ptr;

    if (ptr = malloc(num)) *ptr = x;
    return ptr;
}
int main()
{
    char *p = new('*') char;
}
Observe the following:
1.    This time, the overloaded new takes in an additional parameter – x, of type char.
2.    Such an overloaded new is called when invoked with an argument (‘*‘ in main, of type char).
3.    Note that there need not be any connection between the type for which memory is being allocated and the type of the parameter in new.
4.    Such a new operator (that takes arguments) is called the placement new operator.
5.    Like this, we can have any number of new operators with varying number of arguments and types
6.    The code inside is left to the programmer. In our example, we have initialized the character for which memory was allocated, by the parameter.
 

Thus, while we can have any number of overloaded new operators, we can have only a single overloaded delete operator. Do remember that there are 2 forms of delete though! And also do remember that it is a good programming habit to overload both new and delete, or none of them; which means I would consider it bad if you overload new without overloading delete or vice-versa.
So far we have been considering overloading new and delete in the global scope. It is also possible for us to overload new and delete within classes. This would restrict their scope and operations to that class. Perhaps a simple illustration will throw more light:
class A
{
public:
    void* operator new(size_t num)
    {
        //...
    }
};

class B
{
public:
    void* operator new(size_t num)
    {
        //...
    }
};

class C
{
};

int main()
{
    A *a = new A(); // Will call A's new operator
    B *b = new B(); // Will call B's new operator
    C *c = new C(); // Will call the global new operator
    char *ptr = new char;

    //...
}
As can be seen from the program, when the new operator is used to create an instance of A dynamically, the overloaded new operator of class A is used. The same rule holds good for class B. However, in the case of instantiating class C, the global new is used since there is no overloaded new operator in that class. The same rules hold good for the delete operator too. Thus, new and delete overloads can be present on a per-class basis.
Within these “local” new and delete overloads, if you wish to call the global new to allocate memory, you can continue to use the scope resolution operator (::) like this: ::new <whatever>.


To conclude this article, consider a very practical use of overloaded placement new operator within a class. Consider a class called LinkedList that implements a linked list of nodes, where each node is represented by an object of class Node. Let us say we want to create a node with its data as 10, and append it to the LinkedList object list1. Consider the possibility below:
Node *nodePtr = new(list1) Node(10);
At one go, we are achieving the following:
1.    Creating a node dynamically (thanks to new)
2.    Initializing that node to the value 10 (thanks to a constructor in Node class)
3.    Appending the new node at the end of the linked list list1 (thanks to placement new)
Of course, the Node constructor and placement new in LinkedList class needs to be defined by the programmer.


Source:

Overloading Arithmetic operators in c++

Some of the most commonly used operators in C++ are the arithmetic operators — that is, the plus operator (+), minus operator (-), multiplication operator (*), and division operator (/). Note that all of the arithmetic operators are binary operators — meaning they take two operands — one on each side of the operator. All four of these operators are overloaded in the exact same way.

Overloading operators using friend functions

When the operator does not modify its operands, the best way to overload the operator is via friend function [If the operators (such as increment, decrement and dereference) modify the operands then they should be members of the class].  None of the arithmetic operators modify their operands (they just produce and return a result), so we will utilize the friend function overloaded operator method here.

class Cents
{
  private:
          int m_nCents;
  public:
          Cents(int nCents) { m_nCents = nCents; }
          // Add Cents + Cents
          friend Cents operator+(const Cents &c1, const Cents &c2);
          int GetCents() { return m_nCents; }
};
 
    // note: this function is not a member function!
    Cents operator+(const Cents &c1, const Cents &c2)
    {
      // use the Cents constructor and operator+(int, int)
         return Cents(c1.m_nCents + c2.m_nCents);
    }

    int main()
    {
        Cents cCents1(6);
        Cents cCents2(8);
        Cents cCentsSum = cCents1 + cCents2;
        std::cout << "I have " << cCentsSum .GetCents() << " cents." << std::endl;

        return 0;
    }

Output:
I have 14 cents.
 
Source:
LearnCPP.com

new and delete operators in c++

The syntax for new is:
p_var = new typename;
where p_var is a previously declared pointer of type typename. typename can be any basic data type or user-defined object (enum, class, and struct included). If typename is of class type, the default constructor is called to construct the object.

To initialize a new variable created via new, use the following syntax:
p_var = new type(initializer);
where initializer is the initial value assigned to the new variable, or if type is of class type, initializer is the argument(s) to a constructor.

new can also create an array:
p_var = new type [size];
In this case, size specifies the length of one-dimensional array to create. The address of the first element is returned and stored into p_var, so
p_var[n-1]
gives the value of the nth element (counting from 0)

Memory allocated with new must be deallocated with delete to avoid a memory leak. Arrays allocated with new[] must be deallocated with delete[].
int *p_scalar = new int(5); //allocates an integer, set to 5. (same syntax as constructors)
int *p_array = new int[5];  //allocates an array of 5 adjacent integers. (undefined values)

Initializers cannot be specified for arrays created with new. All elements of an array are initialized with the default constructor of the type. If the type does not have a default constructor, this is a compile-time error.

Releasing dynamically allocated memory

Any memory dynamically allocated with new must be released with a delete command. There are two variants: one for arrays and one for single objects.
int *p_var = new int;
delete p_var;
p_var = 0;
int *p_array = new int[50];
delete[] p_array;
p_array = 0;
Note that the compiler is not required to generate a diagnostic message for using the wrong delete. Furthermore, using the inappropriate deallocator will result in undefined behaviour.

Reallocating memory allocated by new[]

In contrast to C’s realloc it is not possible to directly reallocate memory allocated with new[]. To extend or reduce the size of a block, one must allocate a new block of adequate size, copy over the old memory, and delete the old block. The C++ standard library provides a dynamic array that can be extended or reduced in its std::vector template.

Source:
Wikipedia

Basics of overloading in c++

1) Functions can be overloaded but not classes.
2) Function overloading is not possible for the following scenarios:
·         Differs only in return type
For example: void function(int x);
                    int function(int x);
-because return type is not part of the signature. Signature of a function comprises of Function name, Number of Arguments and Type of Arguments.
·         Differs in static and non-static member functions
For example: static void function(int x);
                           void function(int x);
·         Array and pointer declaration
For example:  void function(int *ptr);
void function(int array[]);
-because an array is implicitly converted to a pointer.
3) When the operator does not modify its operands, the best way to overload the operator is via friend function. If the operators (such as increment, decrement and dereference) modify the operands then they should be members of the class.
4) Operators that cannot be overloaded are:
·         Member – a.b
·         Pointer to member by reference – a.*b
·         Ternary conditional – a?b:c
·         Scope resolution – a::b
·         Pointer to member – a::*b
·         Sizeof – sizeof()
·         Type identification - typeid(object)
·         Cast operators – dynamic_cast, 
                            static_cast, 
                            const_cast and 
                            reinterpret_cast