Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Different ways of using C++ constructors

What the difference between A a1(5); and A a2 = A(5) ? Both of the works, but I really want know the difference between them, because I used method 2 in one of my project and I suffered from a bug which is fixed after I change to method 1. Thanks in advance!

class A {
public:
    int val;
    A() : val(0) {}
    A(int newVal) : val(newVal) {}
};

int main()
{
    A a1(5);  // method 1
    A a2 = A(5); // method 2
}
like image 684
Bon Avatar asked Feb 21 '23 02:02

Bon


2 Answers

A a1(5);  // method 1
A a2 = A(5); // method 2

The first one is called direct initialization, the second one is called copy-initialization.

The second one will NOT compile if you make the copy-constructor inaccessible or/and don't define it as:

class A {
public:
    int val;
    A() : val(0) {}
    A(int newVal) : val(newVal) {}
private:
    A(A const&);  //the second one will not compile
};

Now the second one will not compile. Note that it will not compile in both cases:

  • If the copy-constructor is defined, but is inaccessible (either it is private or protected).
  • If the copy-constructor is declared, but not defined.
like image 132
Nawaz Avatar answered Mar 05 '23 07:03

Nawaz


Strictly speaking, reading your question I expected you to provide these two examples

A a1(5);  // method 1
A a2 = 5; // method 2

The first one is direct-initialization. The second one is copy-initialization.

The examples you provided in your question actually already illustrate the difference between the two :)

Direct-initialization initializes the target object directly, as a single-step process by finding and using an appropriate constructor. Copy-initialization is conceptually a two-step process: first it constructs a temporary object of type A by some conversion constructor and then it copies it to the destination object by using a copy-constructor. I.e.

A a2 = 5;

will actually work as

A a2 = A(5);

And that actually exhaustively explains the difference.

The two-step structure of the second variant is, again, conceptual. The compilers are allowed (and will) optimize the second variant so that it will work exactly as the first one. They will eliminate the intermediate temporary object and perform initialzation directly.

like image 22
AnT Avatar answered Mar 05 '23 08:03

AnT