Constructor

Same named function of class. Ctr is called when object of class is created. Used to provide values to data members.
Return type=None, Cannot access to address of ctr, Inheriting ctr=Cannot
PRIVATE SCOPED CTR*: Can ctr be inside private section(Yes. Single DP)

Ctr calling Hierarchy (Base Class > Derv Class Ctr)

Base class constructor should be defined

Ctr Initializer list

Derived class object also have inherited properties of Base class,
and only base class constructor can properly initialize base class members

class A{
    public:
        A() { cout << "base ctr";  }
        ~A() { cout << "base dtr";  }
};
    
class B: public A {
    public:
        B() { cout << "Derv ctr";  }
        ~B() { cout << "Derv dtr";  }
};
int main(){
    B obj;
}
$ a.out
base ctr
Derv ctr
Derv dtr
Base dtr
            

class A{
    public:
        A();
        ~A();
};
class B: public A {
public:
    B() { cout << "B ctr";  }
    ~B() { cout << "~B";  }
};
int main(){
    B obj;
}
# ./a.out
Error cannot find A::A()
                
In the initializer list, the order of execution takes place according to the order of declaration of member variables.

class test{
    int a; //Declared 1st
    int b; //Declared 2nd
public:
    test (int x): b(x), a(b * 2) {
        cout << b << a;       //b=10, a=garbage
    }
};
int main() {
    test obj(10);
    return 0;
}
$ ./a.exe
b = 10
a = garbage value
This is because, a is declared before b. Initialization of a will happen before b.
Since a = b*2, and b does not have value hence a is initialized to garbage.
        

Types of Constructors

1. Copy Constructor

Copy Ctr is L Value Refererence. Creates copy of object
Default Copy Constructor(Shallow Copy) User-Defined Copy Constructor (Deep Copy)
If you don't define a copy constructor, the compiler provides a default one that performs a shallow, member-wise copy.
This works well for simple classes without dynamically allocated memory.

#include <iostream>
using namespace std;

class A {
	int a;
public:
    // Default copy ctr. Does not have &
	A(int x):a(x) {}
	void print() { cout << a << "\n"; }
};
int main() {
	A obj1(1);
	A obj2(obj1);
	A obj3 = obj1;
	obj3.print();       //1
	obj2.print();       //1
	return 0;
}
            
A user-defined copy constructor is necessary when a class has a pointers to dynamically allocated memory.
The default shallow copy would cause both objects to point to the same memory location, (e.g., a double-free error) when freed
user-defined constructor below performs a deep copy by allocating new memory for the copied object.

#include <iostream>
#include <cstring>
using namespace std;

class A {
	char *a;
public:
	A(const char* x) {
		a = new char[strlen(x)+1];
		strcpy(a, x);
	}
    // Deep copy ctr
    // The argument to the copy constructor is const reference:
    //  This prevents accidental modification of the source object
    //  and to avoid infinite recursive calls during object creation
	A(const A& obj) {
		a = new char[strlen(obj.a) + 1];
		strcpy(a, obj.a);
	}
	~A() {
		delete[] a;
	}
	void print() {
		cout << a << endl;
	}
};
int main() {
	A obj1("Hello");
	A obj2 = obj1;
	obj2.print();           //Hello
	return 0;
}
            

2. Move Constructor(rvalue reference) (Introduced in c++11)

Move Semantics?

Helps transfer of ownership of resources from one object to another without performing an deep copy.
Move constructor implements move semantics

Move Constructor

Moves the object.
Useful for temporary objects (rvalues) which are about to be destroyed anyway, instead of creating new deep copied object, Just transfer the ownership

using vi = vector <int>;
class A {
    vi a;
    void print() {
        for (decltype(auto)i:a)
            cout << i;
    }
public:
    //A(vi&& b):a(b)       ///////// This will make copy. Not correct move ctr ///////////
    A(vi&& b):a(move(b)) {  // move ctr (using rvalue ref).
        cout << "\nmove ctr\n";
        print();
    }
};
int main() {
    vi a = {1,2,3};
    A obj(a);           // Copy ctr called. Local copy remains present

    // move invokes a r value ref
    A obj1(move(a));            // move(a) is equal to (int &&x = a)
    cout << "\nAfter move ctr in main()\n";
    for(decltype(auto)i:a)
        cout << i;
}
/*
$ ./a.out
move ctr
1 2 3

After move ctr in main()    //Value moved not availble in main
$
*/