0

I'm reading Section 4.2.3 Initializing Containers, Tour of C++ Second Edition.

It says:

Vector read(istream& is)
{
     Vector v;
     for (double d; is>>d;)
         v.push_back(d);
     return v;
}

... The way to provide Vector with a move constructor, so that returning a potentially huge amount of data from read() is cheap, is explained in §5.2.2:

Vector v = read(cin);  // no copy of Vector elements here

Is it guaranteed that the above expression will be copy-elided (in C++17)? I think v in the return is an lvalue & a local variable, so it can be copy-elided but is not guaranteed to be elided. Am I missing something here?

Jay Lee
  • 1,684
  • 1
  • 15
  • 27
  • In Pre-C++17 it was not guaranteed, in C++17 onwards it is guaranteed. I do believe someone will answer this question with tons of references. – Croolman Apr 25 '20 at 10:29
  • @Croolman Is it true? As far as I know, only prvalues in return statements are guaranteed to be copy-elided in C++17 onwards. I'm not an expert, so please let me know if it is not the case. – Jay Lee Apr 25 '20 at 10:33
  • NRVO is not guaranteed in C++17, so the move constructor still needs to be visible. – L. F. Apr 25 '20 at 10:43
  • Or rather, this: [How does guaranteed copy elision work?](https://stackoverflow.com/q/38043319/9716597) – L. F. Apr 25 '20 at 10:44
  • @L.F. Thank you for the comments. I'm actually aware of the first question, and I just checked the second one. It says that NRVO is not guaranteed, as you mentioned. I was trying to make sure if I was correct, as the book is written by Stroustup himself. So apparantly, he oversimplified the problem, am I right? – Jay Lee Apr 25 '20 at 11:01
  • 1
    @JayLee Stroustrup wrote "no copy of elements" which is accurate. If NRVO doesn't apply here, the move constructor is (guaranteed to be) called instead of copy constructor, per [\[class.copy.elision\]](https://timsong-cpp.github.io/cppwp/n4659/class.copy.elision#3.1). So elements are guaranteed to be left untouched, regardless of whether NRVO is applied. – L. F. Apr 25 '20 at 11:04
  • @L.F. Oh.. I have been blinded by concentrating on the `v` itself. Thank you for clarifying, it solved my question! (I'm not sure if the other SO posts you linked answers my question tho.) – Jay Lee Apr 25 '20 at 11:22
  • @ChrisMM The last sentence of the accepted answer is the point I needed a clarification. – Jay Lee Apr 25 '20 at 13:34
  • @JayLee Hopefully, this problem will be gone in C++23: wg21.link/p2025 – Anton3 Jul 05 '20 at 13:21

1 Answers1

1

Is it guaranteed that the above expression will be copy-elided (in C++17)?

I think v in the return is an lvalue & a local variable, so it can be copy-elided but is not guaranteed to be elided. Am I missing something here?

From copy_elision

Non-mandatory elision of copy/move (since C++11) operations

In a return statement, when the operand is the name of a non-volatile object with automatic storage duration, which isn't a function parameter or a catch clause parameter, and which is of the same class type (ignoring cv-qualification) as the function return type. This variant of copy elision is known as NRVO, "named return value optimization".

So NRVO is not guarantied, even in C++17.

But, if not applied, move-constructor is done (See return statement for details).

Community
  • 1
  • 1
Jarod42
  • 203,559
  • 14
  • 181
  • 302