A constructor is the special member function that runs automatically the moment an object is born. Its whole job is to leave the object in a valid, fully-initialized state so nobody ever touches a "half-built" object. Think of it as the factory line that stamps every new object before it ships. Different flavours of constructor exist because objects get born in different ways: from nothing (default ), from supplied values (parameterized ), from an existing object (copy ), or by reusing another constructor's logic (delegating ).
A constructor is a member function that:
has the same name as the class ,
has no return type (not even void),
is called implicitly when an object is created.
It cannot be virtual (a normal one), and you can have many overloaded versions.
Definition Default constructor
A constructor that can be called with no arguments . Either you write ClassName(), or the compiler synthesizes one for you only if you declare no other constructor .
So you can write Point p; or build arrays Point arr[10];. Each element must be born somehow — the default constructor supplies the "born from nothing" recipe.
Worked example Writing one
class Point {
int x, y;
public:
Point () : x ( 0 ), y ( 0 ) {} // member-initializer list
};
Point p; // x=0, y=0
Why the : x(0), y(0) part? Members are initialized in the initializer list before the body runs. Doing x = 0; inside {} is assignment after default-init , which is wasteful for class members and impossible for const/reference members.
Common mistake "If I write a parameterized constructor, I still get the default one free."
Why it feels right: the compiler is "helpful" elsewhere, so you assume it always hands you a default.
The truth: once you declare any constructor , the compiler stops synthesizing the default. Point p; then fails to compile.
The fix: explicitly bring it back with Point() = default;.
Definition Parameterized constructor
A constructor that takes one or more arguments to initialize the object with caller-supplied values.
class Point {
int x, y;
public:
Point ( int a , int b ) : x (a), y (b) {}
};
Point p ( 3 , 4 ); // x=3, y=4
Why initializer list again? Direct-initializes x from a in one step — no temporary default value.
explicit vs implicit conversion
class Meter { public: Meter ( int m){} };
Meter m = 5 ; // compiles! 5 silently becomes Meter(5)
Why it feels harmless: looks like assignment. Problem: unexpected hidden conversions. Fix: mark single-arg constructors explicit Meter(int m); so Meter m = 5; is rejected but Meter m(5); works.
Definition Copy constructor
A constructor that creates a new object as a copy of an existing one . Signature:
ClassName(const ClassName& other); \texttt{ClassName(const ClassName\& other);} ClassName(const ClassName& other);
const &?
& (reference): if you took the argument by value , copying into the copy constructor would itself call the copy constructor → infinite recursion . A reference avoids the copy.
const: you only want to read the source, and you must accept const and temporary sources too.
Worked example WHY you MUST write one (deep copy)
class Buf {
int* data; int n;
public:
Buf ( int n ) : data ( new int [n]), n (n) {}
Buf ( const Buf & o ) : data ( new int [o.n]), n (o.n) { // deep copy
for ( int i = 0 ;i < n;i ++ ) data[i] = o.data[i];
}
~Buf (){ delete[] data; }
};
Why this step (new int[o.n])? The compiler's default copy constructor does a shallow copy — it just copies the pointer value. Then two objects own the same memory , and both destructors delete[] it → double free / crash. Deep copy gives each object its own buffer.
Common mistake "Default copy constructor is always fine."
Why it feels right: for Point{x,y} it genuinely is — member-wise copy of ints works.
The truth: the moment a class owns a raw resource (heap pointer, file handle), member-wise (shallow) copy is a bug. Rule of Three: if you write a destructor, you almost certainly need a copy constructor and copy assignment too.
Definition Delegating constructor
A constructor that calls another constructor of the same class in its initializer list, to avoid duplicating initialization code .
DRY — Don't Repeat Yourself. If Point() and Point(int) both need to set up the same state, write the logic once in the most general constructor and let the others delegate to it.
class Point {
int x, y;
public:
Point ( int a , int b ) : x (a), y (b) {} // target (master)
Point () : Point ( 0 , 0 ) {} // delegates
Point ( int a ) : Point (a, a) {} // delegates
};
Why : Point(0,0)? The delegate's initializer list contains only the call — you cannot also init members there. The target runs fully first, then the delegating constructor's body runs.
Common mistake Delegation cycle
A () : A ( 0 ) {} // WRONG if...
A ( int ){ /* ... */ : A () {} } // ...this loops back
Why it feels okay: each looks like reuse. Problem: A()→A(int)→A() is a cycle → undefined behaviour / infinite loop. Fix: ensure delegation forms a tree ending at a real "target" constructor.
Common mistake "Members init in the order I wrote them in the list."
Why it feels right: the list reads top-to-bottom. Truth: init order = declaration order in the class . Writing : b(a), a(5) while a is declared after b means b is built using an uninitialized a . Fix: match list order to declaration order; turn on -Wreorder.
What three properties define a constructor? Same name as class, no return type, called implicitly at object creation.
When does the compiler stop generating a default constructor for you? As soon as you declare any other constructor; restore it with = default.
Why must the copy constructor take its parameter by reference? By value would itself invoke the copy constructor → infinite recursion.
Why const in ClassName(const ClassName&)? You only read the source, and it lets you copy from const objects and temporaries.
Shallow vs deep copy problem? Default copy copies pointers, so two objects share memory → double free in destructors; deep copy allocates a separate buffer.
State the Rule of Three. If you define a destructor, copy constructor, or copy assignment, you probably need all three.
What is a delegating constructor and its one restriction? A constructor that calls another of the same class in its init list; that call must be the ONLY thing in the list (no extra member inits).
In what order are members initialized? In the order they are DECLARED in the class, not the order in the initializer list.
What does explicit on a single-arg constructor prevent? Implicit conversions like Meter m = 5;.
Three situations that fire the copy constructor? Copy-initialization (T b=a), pass-by-value, return-by-value.
Recall Feynman: explain to a 12-year-old
Imagine a toy factory. Every time a new toy comes off the line, a worker must set it up so it's ready to play with. That worker is the constructor .
Default : builds a plain toy with standard parts when you don't say anything special.
Parameterized : you hand the worker a colour and size, and they build that toy.
Copy : you point at a finished toy and say "make me one exactly like that." If the toy has its own toy-dog, a lazy copy gives both toys the same dog (they fight over it!). A deep copy gives the new toy its own dog.
Delegating : instead of teaching every worker the full setup, one master worker knows it, and the others just say "hey master, you do it."
Mnemonic Remember the four flavours
"De-Par-Co-De" → De fault (nothing), Par ameterized (values), Co py (clone), De legating (reuse). And for copy safety: "Three's company" = Rule of Three (destructor + copy ctor + copy assign travel together).
Intuition 80/20 — the 20% that matters most
Declaring any constructor kills the free default → use = default.
Copy ctor = const& + deep copy when you own a resource.
Members init in declaration order , not list order.
Delegate to kill duplicate init code.
Constructor: same name, no return type, implicit
Enables Point p and arrays
const and reference members
Intuition Hinglish mein samjho
Constructor ek special function hai jo object ke "janam" ke time automatically chalta hai. Iska kaam hai object ko ek valid, ready-to-use state mein le aana taaki koi bhi half-built object ko use na kar paaye. Iska naam class ke naam jaisa hota hai aur iska koi return type nahi hota.
Char flavours yaad rakho. Default — bina argument ke (Point p;), zero/standard values set karta hai. Parameterized — tum values do (Point p(3,4)), wahi set hoti hain. Copy — kisi existing object se naya clone banata hai, signature Point(const Point&). Yahan & zaroori hai warna by-value lene se copy constructor khud ko hi call karta rahega — infinite recursion ! Aur const isliye taaki source ko sirf padho. Delegating (C++11) — ek constructor doosre constructor ko init-list mein call karta hai, code repeat na karna pade.
Sabse important trap: jaise hi tum koi constructor likhte ho, compiler free wala default constructor dena band kar deta hai — wapas chahiye to Point() = default; likho. Doosra bada trap: agar class koi raw pointer/heap memory own karti hai, to default (shallow) copy do objects ko same memory dega aur dono destructors usko delete karenge — double free crash . Solution: apna copy constructor likho jo deep copy kare (naya buffer allocate karke). Yahi hai Rule of Three — destructor likha to copy constructor aur copy assignment bhi chahiye.
Last cheez: members hamesha class mein declare kiye gaye order mein initialize hote hain, init-list ke order mein nahi. Isliye list ka order declaration ke order se match rakho, warna uninitialized member use ho sakta hai. Ye chhoti chhoti baatein hi exam aur real bugs dono mein 80% kaam karti hain.