3

here i am using two syntax to pass values to a constructor :-

class A   
{

public:
    int x,y;

    A(int a,int b) : x(a),y(b){}
    void show()
    {
        cout<<x<<" "<<y<<endl;
    }
};

int main()
{

    A obj1={5,6};//first method
    A obj2(9,10);//second method

    obj1.show();
    obj2.show();
}

And both are working fine but when i remove the constructor function itself then also the first method is working fine . please explain this.

Geezer
  • 5,600
  • 18
  • 31

2 Answers2

7

When you remove this constructor, class A becomes eligible for aggregate initialization, which is caused here by this curly braces syntax: A obj1={5,6}; (that also has this equivalent form: A obj1{5,6}; since C++11)

As you can read here, this applies in your case as class A then has none of the following:

  1. private or protected non-static data members (applies until C++11)
  2. user-declared constructors (applies since C++11 until C++17)
  3. user-provided constructors (explicitly defaulted or deleted constructors are allowed) (applies since C++17 until C++20)
  4. user-provided, inherited, or explicit constructors (explicitly defaulted or deleted constructors are allowed) (applies since C++20)
  5. user-declared or inherited constructors
  6. virtual, private, or protected (applies since C++17) base classes
  7. virtual member functions
  8. default member initializers (applies since C++11 until C++14)

In contrast, this syntax: A obj2(9,10); is performing direct-initialization, and it fails to compile once you remove the constructor due to [dcl.init¶17.6.2]:

[...] if the initialization is direct-initialization [...] constructors are considered. [...] If no constructor applies [...] the initialization is ill-formed.


Prior to removing the constructor, the same syntax A obj1={5,6}; was calling it, while performing copy-list-initialization.


What is aggregate initialization? It is the initialization of an instance of an aggregate type (either an array or a struct/class adhering to the above list) by the braced-init-list syntax. The arguments inside the braces must match the struct/class non-static data members in declaration order. It got significant boost in later versions of C++, as more syntactic forms for it were added to the language. Your usage of ={...} is the only one in existence from before C++11.


The general pros and cons of using parentheses forms of initialization vs. brace initialization is discussed by many. A good place to get a comprehensive readout is at Item 7 of Scott Meyers' Effective Modern C++. That said, the foremost advantage of all brace initialization forms is that they don't allow narrowing.

Geezer
  • 5,600
  • 18
  • 31
1
A obj1={5,6};

This is using list initialization for the object, which is perfectly valid even without your 2 argument constructor being defined.

This may help you understand: Why is list initialization (using curly braces) better than the alternatives?

Mike
  • 4,722
  • 1
  • 27
  • 40
  • 1
    Good call @3Dave, was just updating to clarify when I saw your comment :) – Mike Sep 14 '18 at 18:09
  • Also, nice link - I had no idea the brace initialization was that helpful. – 3Dave Sep 14 '18 at 18:10
  • does list initialization use some sort of internal constructor calling. what is the mechanism? is it simply used to make the structures of c++ behave like c structures – Mohammad Fraz Sep 14 '18 at 18:13