c++constructordefault-constructorexplicit-constructor

What is the difference between implicit constructors and default constructors?


This is very trivial, but Czech language (my native) doesn't distinguish between implicit and default, so I am confused by some Czech translations what is the difference between implicit and default constructor or constructor call.

struct Test {
  Test(int n=0) { }
};

Can you describe in these terms what the following statements do?

  1. Test t1;
  2. Test t2();
  3. Test t3 = 3;
  4. Test t4(4);
  5. Test t5 = Test(5);

Solution

  • The terms default and implicit, when talking about a constructor have the following meaning:

    In simple terms, a constructor is default if it can be called with no arguments. A constructor is implicit(ly declared/defined) if it is not provided by the user but declared/defined.

    As of the specific cases:

    Test t1;
    

    Uses the default constructor, Test(int = 0), which is not implicit.

    Test t2();
    

    This is a strange quirk of the language, it declares a function that takes no arguments and returns a Test object.

    Test t3 = 3;
    

    This is called copy-initialization and is equivalent to the composition of an implicit* conversion from 3 to Test and copy construction of t3 from the result of the conversion. This will use the Test(int) constructor for the conversion, and then the implicitly defined (and declared) copy constructor. Note: the compiler can optimize away the copy, but it must verify that the copy constructor is available (access specifiers) and can be defined.

    Test t4(4);
    

    Uses the Test(int) constructor, which in this case is not acting as a default constructor.

    Test t5 = Test(5);
    

    Equivalent to the Test t3 = 3 case, with the only difference that the conversion from 5 to Test is explicit in this case. In this example it won't matter, but if the constructor had been marked as explicit this line would compile while the t3 case would fail.


    *) Yet another use of implicit, in this case referring to the fact that the conversion from 3 to Test is not explicitly requested in the code. Compare this with t5 where the conversion is explicitly requested by the programmer: Test(5).