2

In C++, is there any semantic difference between the following 3 methods of initialization?

T t;
T t = T();
auto t = T();

I'm interested in differences w.r.t. copy constructor, destructor and assignment operator behavior.

Matt Fichman
  • 5,458
  • 4
  • 39
  • 59

1 Answers1

2

They are not equivalent. The first one leaves t uninitialized if it's a POD type, whereas the latter two will value-initialize the object no matter what. Example:

#include <iostream>

using namespace std;

int main()
{
    int a = int();

    cout << a << endl;
    return 0;
}

results in:

$ clang++ -O2 -o init init.cpp
$ ./init
0

whereas this:

#include <iostream>

using namespace std;

int main()
{
    int a;

    cout << a << endl;
    return 0;
}

will output some garbage (or crash, or make demons fly out of your nose) since it has undefined behavior arising out of the uninitialized object:

$ clang++ -O2 -o init init.cpp
$ ./init
1348959264

As to the question of copy constructors and assignment operators: the second and third snippets may invoke one of them (or may not, thanks to copy elision), so either of them (or both) need to be available.

  • This might answer FoggyDay's comment but not OP's question – Marco A. Aug 23 '14 at 18:11
  • @Deduplicator Maybe also if `T` is a union or array-of-primitive? If `T` is a class type, then one thing is sure: it **will** invoke the default constructor, so it won't leave the object uninitialized. – The Paramagnetic Croissant Aug 23 '14 at 18:13
  • 1
    Default-initialization occurs only if it's a non-POD type. – David G Aug 23 '14 at 18:13
  • @MarcoA. Apart from the first part of the question (which my answer does address), the clause "w.r.t. copy constructor, destructor and assignment operator behavior" doesn't make much sense, since there's nothing that would invoke the copy constructor, the destructor or the assignment operator in the piece of code OP posted. – The Paramagnetic Croissant Aug 23 '14 at 18:15
  • I thought `T t = x;` was equivalent to `T t(x);`. If `x` is of type `T`, why wouldn't the copy constructor be involved? – jxh Aug 23 '14 at 18:20
  • 1
    Well, the 2nd and 3rd examples *would* invoke the move constructor or the copy constructor, if not for copy elision. But regardless of whether or not those constructors are invoked, one of them is at least required to not be deleted. The first example does not have that requirement, so that is another difference. – Benjamin Lindley Aug 23 '14 at 18:20
  • @jxh oh well, that's absolutely right. – The Paramagnetic Croissant Aug 23 '14 at 18:21
  • @BenjaminLindley Yeah, you are right, sorry about that. If you think that this difference is worth mentioning, feel free to edit it into my answer. – The Paramagnetic Croissant Aug 23 '14 at 18:22
  • You are conflating *default-initialization*, which may result in no initialization being performed, with *value-initialization*, which is what `T()` does. – T.C. Aug 23 '14 at 19:00
  • @T.C. Right, changed that, thanks. (C++ really just has too many subtypes of the same thing with regards to semantics...) – The Paramagnetic Croissant Aug 23 '14 at 19:04
  • @BenjaminLindley That's what I was getting at. In the 2nd and 3rd examples, there is no copy constructor/assignment operator call due to copy elision, correct? – Matt Fichman Aug 23 '14 at 19:32
  • @MattFichman copy elision may or may not be done, so the copy constructor may or may not be invoked. – The Paramagnetic Croissant Aug 23 '14 at 19:34
  • @MattFichman Yes, I believe that is correct. Answer edited. – The Paramagnetic Croissant Aug 23 '14 at 19:44
  • 1
    The second and third may invoke the copy constructor, but will never invoke assignment operators. – T.C. Aug 23 '14 at 21:03
  • @T.C. that's interesting, but why are those operators required to be non-`delete`d then (if the copy constructors are deleted)? – The Paramagnetic Croissant Aug 23 '14 at 21:05
  • @TheParamagneticCroissant Huh? If the copy ctor is deleted then neither 2) nor 3) would compile unless you have a move ctor available. Whether you have an assignment operator defaulted or deleted is irrelevant. – T.C. Aug 23 '14 at 21:08