1

C++ Primer (5th edition) states on page 499 that the compiler is permitted to substitute

string null_book = "9-999-9999-9"; // copy initialization

for

string null_book("9-999-9999-9"); // compiler omits the copy constructor

On the other hand, this post shows that (in general) the two forms can produce different results.

How can I reconcile the statement from C++ Primer with the cited post?

Community
  • 1
  • 1
AlwaysLearning
  • 7,257
  • 4
  • 33
  • 68
  • In this case you are working with `std::string` so I think there is no difference. – coincoin Jul 19 '15 at 19:08
  • @coincoin I realized this and added the words "(in general)" to be clear that I refer to this behavior of the compiler in the most general context. I believe that **C++ Primer** meant the general context although they used this example with strings. – AlwaysLearning Jul 19 '15 at 19:14

2 Answers2

5

The book is trying to illustrate copy elision using normal C++ code. It does not mean that the compiler is allowed to change copy-initialization to direct-initialization, even though in the case of the initialization you show, copy-initialization-with-copy-elision has the same effect as direct-initialization.

The only change in observable behavior allowed is eliding calls to the copy/move constructor and the destructor. The other constructor called is never changed. Thus:

struct Meow {
    explicit Meow(int); // #1
    Meow(double);       // #2
    Meow(const Meow&);  // #3
};

Meow m = 1;     // OK, always call #2, may or may not call #3
Meow n(1);      // OK, call #1, never call #3
Meow p = {1};   // Error: copy-list-initialization selected explicit constructor
Meow q{1};      // OK, call #1, never call #3
Meow r = {1.0}; // OK, call #2, never call #3 
T.C.
  • 133,968
  • 17
  • 288
  • 421
0

Yes, this is one of many situations, governed by the rules of copy elision ([class.copy]), in which the compiler may produce a temporary object but is not required to do so.

Formally, when you u is a value of type U and T is constructible from U, then the initialization T t = u; means that t is constructed from a temporary constructed from u as if you had written T t = T(u);. However, this copy may (and usually is) elided, and the effect is that of T t(u);, only that copy initialization requires that the constructor be non-explicit.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • But what about the post that I cited? There this pre-condition is met and still different results are obtained by using direct initialization... – AlwaysLearning Jul 19 '15 at 19:22
  • @MeirGoldenberg: The rules for copy elision explicitly allow the elision even if the copy constructor has side effects. So you can indeed get different outputs depending on how many temporaries are being used. – Kerrek SB Jul 19 '15 at 19:34
  • Do you mean that the code in the cited post is an example of undefined behavior? – AlwaysLearning Jul 19 '15 at 19:35
  • @MeirGoldenberg: No, I don't mean that at all. What is giving you that impression? – Kerrek SB Jul 19 '15 at 19:37
  • Because the compiler is allowed (but not required) to change copy initialization in that code by direct initialization. Depending on what the compiler chooses to do, different results will be produced. – AlwaysLearning Jul 19 '15 at 19:38