Why does calling with empty parenthesis not call the default constructor?

  c++, class, constructor, default-constructor


According to the tutorial, if a class defines a default constructor Rectangle();, it’sinvoked via:

int main () {
    Rectangle recta; // valid - default constructor
    Rectangle rectb(); // valid - but not a default constructor
    Rectangle rectc{}; // valid - default constructor

It is said that the second call is a "function declaration", so its interpreted by the compiler as some function that returns an object of type Rectangle. Yet in the subsequent sections of that same tutorial, it refers to Rectangle(); as a default constructor.


So this is a two part question:

  1. Why are default constructors defined with () if calling with () does not even invoke them?
  2. Why does the use of {} invoke the default constructor if defined with ()?


W.R.T the first item, it seems contradictory that the default constructor definition must be either:

  • Completely omitted, or
  • Defined with empty parenthesis

Yet calling with empty parenthesis does not invoke the default constructor. The best that I can reason is that the compiler interprets the call to rectb() as some kind of "inline" function definition that returns an object of type Rectangle; because of this, if the default constructor had member assignment in it, this newly returned object would not have any members assigned and would all be NULL (or so I believe).

Now to expand the confusion with a detailed example:

#include <iostream>
using namespace std;

class Circle
    Circle(); // M1
    Circle(float r); // M2

    cout << "default constructor" << endl;

Circle::Circle(float r)
    cout << "custom constructor" << endl;

int main() {
    Circle c1(1.0); // calls M2
    Circle c2(); // does not call M1
    return 0;

// Outputs
"custom constructor"

So if the compiler interprets a line such as Circle c2(); as a newly declared function returning type Circle, why does it not do that for Circle c1(1.0); and is instead able to find a matching constructor?

W.R.T. the second item, I believe this is the result of a C++11 design implementation that enables to compiler to handle value-initialization from what I’ve read. Since it uses {} and not () the compiler does not parse this as a function declaration.


Now while I am researching this, the other questions I have found include:

  1. Default constructor with empty brackets

Expands on something called the "most vexing parse" in C++, surrounding how Circle c2(); is treated as a function declaration as noted. However, the question (#1) I am asking expands on this, namely why are what appear to be two function declarations treated differently despite having definitions within the class?

  1. C++ default Constructor not being called

Marked as a duplicate of the previous question, but with examples aligned to this post.

Source: Windows Questions C++