4

I saw today a c++ Initialization of a class which I am not familiar with.

CPrice price = CPrice();

The Initialization should normally look like this

CPrice price;

I would have guessed that the first one should throw an error or something. What happens here ? I would guess that the variable is on the stack because it wasn't initialized with new .

I use Visual studio express 2012 with microsofts c++ compiler. Is it maybe something which is microsoft compiler specific and thus allowed ?

Bongo
  • 2,933
  • 5
  • 36
  • 67
  • 1
    I would think they are following some sort of style guide. If you have an `= ` when you create a variable you know it is initialized. – NathanOliver Aug 28 '15 at 13:39
  • Why do you think this should produce an error? `CPrice()` is a constructor that returns an object that is assigned to the freshly declared variable... – 463035818_is_not_an_ai Aug 28 '15 at 13:41
  • @tobi303 Is it assigned with the = or is it copied ( "operator=" )? – Bongo Aug 28 '15 at 13:46
  • 3
    This is an initialisation; there is no assignment here. – Alan Stokes Aug 28 '15 at 13:51
  • 1
    @Bongo Nope, actually in the context of variable declaration `=` means copy. `CPrice price = CPrice();` and `CPrice price(CPrice());` are the same by definition. Welcome to c++ syntax quirks. – luk32 Aug 28 '15 at 13:57
  • The first initialization is safer if you are not absolutely sure `CPrice` is a user type (perhaps you are writing template code for example, or someone has done `using CPrice = int`) because otherwise `price` may be uninitialized. – Chris Drew Aug 28 '15 at 14:50

3 Answers3

8

Both lines are perfectly fine, and end up with the same observable behaviour from the client code point of view: price is a default constructed variable of type CPrice, of course allocated on the stack.


If you want to go into the technicalities, they are not identical:

CPrice price; is a default initialization of a variable price of type CPrice. This is a user type (i.e., a class), so it always mean a call to the default constructor.

CPrice price = CPrice(); is a compound expression that does two things:

  • CPrice(): initializes and anonymous CPrice object (on the stack), by direct initialization (it invokes a constructor with the ()). Since the parentheses are empty, this will call the default constructor.
  • It then copy initializes (before C++11) / move initializes (available to C++11 onward) a variable price of type CPrice, the copied-from/moved-from object being the anonymous CPrice instance.

The longest allocation forces that a copy constructor exists for CPrice, or the code will be in error. But the compiler is allowed to skip the copy construction and optimise it away, by issuing the same code than with the shortest form.
Additionally, in C++11, if a move constructor exists for CPrice, it will be used in place of the copy constructor in this case (that is, if this operation is not entirely removed anyway).

So the only perceivable difference is that the shortest form will compile even if CPrice is not copy constructible. Both forms require CPrice to be default constructible.


One more more or less related precision, coming from the other answer. You could think that an hypothetical middle ground declaration like this would be the same:

CPrice price();

Yet, it is actually completely different: this one declares price to be a function taking no argument (the empty parentheses), and returning a CPrice. It is colloquially known as the most vexing parse.

Ad N
  • 7,930
  • 6
  • 36
  • 80
  • 2
    More than likely the copy will be elided and it will be the same as the second example. – NathanOliver Aug 28 '15 at 13:48
  • 1
    @NathanOliver Even if the copy is elided (which I agree it almost certainly will be) the relevant copy constructor must exist and be callable, so it's not quite the same. – Alan Stokes Aug 28 '15 at 13:50
  • Thank you for your comments ! @NathanOliver: I guess we were writing it at the same time ; ) – Ad N Aug 28 '15 at 13:52
  • @AlanStokes Yeah I forgot it is not using the assignment operator as this is direct initialization and that uses the copy constructor. – NathanOliver Aug 28 '15 at 13:56
  • 1
    In C++11, `CPrice price = CPrice();` `price` may be move constructed, see [here how move constructor is generated by default](http://stackoverflow.com/questions/4819936/why-no-default-move-assignment-move-constructor). – Allanqunzi Aug 28 '15 at 13:59
  • @Allanqunzi Thank you for this important remark ! I updated the answer. – Ad N Aug 28 '15 at 14:02
  • 1
    There's a great Herb Sutter GOTW article on this. You've covered pretty much everything he mentions there, though its still worth a read for anyone confused on this topic: http://herbsutter.com/2013/05/09/gotw-1-solution/ – schanq Aug 28 '15 at 14:26
-1

the assignation is calling the assignment operator (if not deleted) when the instance has already been declared . The first line declares AND explicitly calls a constructor , not really helpful on stack but more in the heap with polymorphism . The second line calls directly its default constructor (if not deleted and if no operator() implemented too )

If you still wonder for the operator = , then explicitly declare in the class declaration
CPrice & operator = (const CPrice &) = delete;

Ericool
  • 1
  • 2
-2

The two lines do exactly the same thing. They both call the default constructor (one with no arguments). Also valid could have been CPrice price();, as this and the first one you have allow you to push arguments if there is a constructor that takes them, whilst your second one would not. Also yes, if the new keyword is not used, then the allocation is on the stack (for simple things like this).

Benjamin James Drury
  • 2,353
  • 1
  • 14
  • 27
  • 1
    what do you mean with "simple things like this"? – 463035818_is_not_an_ai Aug 28 '15 at 13:49
  • Just simple object creation. It seems to me that there's three ways of doing everything in C++ so I was largely covering my back in case someone came along and told me that new wasn't the only way to make new objects on the heap. – Benjamin James Drury Aug 28 '15 at 13:52
  • 2
    `CPrice price();` doesn't do what you think it does: it's a declaration of a function called `price` which takes no arguments an returns a `CPrice` object. See article on [most vexing parse](https://en.wikipedia.org/wiki/Most_vexing_parse). – Nik Bougalis Aug 28 '15 at 13:52
  • @NikBougalis hehe, [classic](https://en.wikipedia.org/wiki/Most_vexing_parse) ; ) – Ad N Aug 28 '15 at 13:54
  • 1
    *"The two lines do exactly the same thing."* No they don't. They have different meanings, although compiler is allowed to optimized the second, to be *effectively* the same. `CPrice price = CPrice();` and `CPrice price(CPrice());` are the same by definition, `CPrice price;` is different in principle. – luk32 Aug 28 '15 at 13:54
  • 1
    Well in that case I've learned something new for today. Am I right in thinking that the very end results are identical though? – Benjamin James Drury Aug 28 '15 at 14:41
  • It depends. http://stackoverflow.com/questions/8758152/disabling-gs-return-value-optimisation, You can play with http://coliru.stacked-crooked.com/a/ffe96f2e68c5a2c0. This option doesn't make the compiler bend the rules. Both program and outputs are equally valid. As opposed to e.g `-ffast-math`. – luk32 Aug 31 '15 at 11:19