4

C++11 brings the new generalized initializers which can be nice. Question: Is any of the old syntax for initializing objects considered deprecated. In C++03 an object can be initialized as

  1. Foo bar(x)
  2. Foo bar=Foo(x)

Option (1) is preferred since it does not involve a copy. In C++11 there are more ways:

  1. Foo bar{x}
  2. auto bar=Foo{x}

With move constructors and assignment operators, option (4) should also be fine. Is (1) considered deprecated in favor of (3) or (4)?

Also, in C++03, the rule is that all constructors taking one argument should be explicit (except copy ctor). Other constructors are always explicit. With generalized initializers, any ctor can be implicit. Is the new rule then to put explicit everywhere, or just where the conversion would imply side effects (allocating a bunch of memory, creating a file...) or be lossy (double to float)?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
user877329
  • 6,717
  • 8
  • 46
  • 88
  • 1
    I think you have a few good questions, but you should really limit yourself to one question per "question". :) – erip Jan 08 '16 at 13:23
  • Perhaps yes, but everything has to do with initializers. – user877329 Jan 08 '16 at 13:24
  • 2
    Not sure but IMO more appropriate version of 2. would be `Foo bar = x` (it would be identical to 1. then), why would anyone explicitly make a temporary object, just to invoke copy c'tor? – luk32 Jan 08 '16 at 13:28
  • @user877329: You can see from the list of existing questions on SO that we do not bundle all questions on a topic into a single question. :) – Lightness Races in Orbit Jan 08 '16 at 14:00
  • @luk32 Certainly true – user877329 Jan 08 '16 at 14:24
  • 1
    @luk32 @user877329 `Foo bar = x` will not compile for explicit ctors which is recommended for single argument ctors. Anyway the copy or move in option (2) & (4) will [typically](http://ideone.com/5BN8jX) be [elided](http://en.cppreference.com/w/cpp/language/copy_elision), so no worries. – Brandlingo Jan 08 '16 at 21:43
  • @MatthäusBrandl I relized that – user877329 Jan 09 '16 at 08:14
  • @MatthäusBrandl Ummm, I forgot to add that it would be nice to explain what type `x` is. I tried later but it was past 5min limit. I've felt it was not worth it. Anyways, obviously things change if we talk about converter constructors (this is the name for those thingies btw). Still, making a temporary copy is not the proper solution. As the name suggests `explicit` prevents the implicit conversion. The proper syntax for this is funnily (for me) quite close, i.e. you just need to move parentheses `Foo bar=(Foo)x`. No temporary copy and the same c'tor will be called. http://ideone.com/J4i69J – luk32 Jan 09 '16 at 21:41
  • @luk32 Concerning the type of `x`, it must be convertible to `Foo` and it does not make much sense that it is `Foo`, because then it's a simple copy. Concerning your suggestion: This is not true, the same temporary copy is elided as before. (your example would not even show the copy if it happened) Next `(Foo) x` is a C-style cast which is [discouraged](https://www.securecoding.cert.org/confluence/display/cplusplus/EXP05-CPP.+Do+not+use+C-style+casts) in C++. You could go for a `static_cast(x)`, but that's just a fancy syntax for `Foo bar = x` or `Foo bar = Foo(x)`. – Brandlingo Jan 10 '16 at 17:51
  • @MatthäusBrandl Oh, my bad, both constructors will be called anyways. I was convinced compiler can cut to the right converting c'tor. Regarding the cast. I was about 5 letters under the character limit, so I couldn't fit `static_cast`. – luk32 Jan 11 '16 at 14:44

1 Answers1

3

Is (1) considered deprecated in favor of (3) or (4)?

Deprecated might not be the best choice of words. brace-initialization is preferred when possible. I mention this because Foo(x) does not always correspond to Foo{x}.

Consider the constructors for std::vector:

std::vector<int> v1(10, 0); // Creates a vector of size 10 initialized with all 0's.
std::vector<int> v2{10, 0}; // Creates a vector with elements {10, 0}.

There's a difference in behavior between ctors; thus, it's not fair to say that (1) should be abandoned in lieu of (3) or (4).

This example sort of answers your second question:

Is the new rule then to put explicit everywhere ... ?

Yes. Because there would be an ambiguity, you don't want the compiler to attempt to resolve it - mark it as explicit.

erip
  • 16,374
  • 11
  • 66
  • 121