Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
184 views
in Technique[技术] by (71.8m points)

c++ - Why are by-value parameters excluded from NRVO?

Imagine:

S f(S a) {
  return a;
}

Why is it not allowed to alias a and the return value slot?

S s = f(t);
S s = t; // can't generally transform it to this :(

The spec doesn't allow this transformation if the copy constructor of S has side effects. Instead, it requires at least two copies (one from t to a, and one from a to the return value, and another from the return value to s, and only that last one can be elided. Note that I wrote = t above to represent the fact of a copy of t to f's a, the only copy which would still be mandatory in the presence of side effects of move/copy constructor).

Why is that?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Here's why copy elision doesn't make sense for parameters. It's really about the implementation of the concept at the compiler level.

Copy elision works by essentially constructing the return value in-place. The value isn't copied out; it's created directly in its intended destination. It's the caller who provides the space for the intended output, and thus it's ultimately the caller who provides the possibility for the elision.

All that the function internally needs to do in order to elide the copy is construct the output in the place provided by the caller. If the function can do this, you get copy elision. If the function can't, then it will use one or more temporary variables to store the intermediate results, then copy/move this into the place provided by the caller. It's still constructed in-place, but the construction of the output happens via copy.

So the world outside of a particular function doesn't have to know or care about whether a function does elision. Specifically, the caller of the function doesn't have to know about how the function is implemented. It's not doing anything different; it's the function itself that decides if elision is possible.

Storage for value parameters is also provided by the caller. When you call f(t), it is the caller that creates the copy of t and passes it to f. Similarly, if S is implicitly constructable from an int, then f(5) will construct an S from the 5 and pass it to f.

This is all done by the caller. The callee doesn't know or care that it was a variable or a temporary; it's just given a spot of stack memory (or registers or whatever).

Now remember: copy elision works because the function being called constructs the variable directly into the output location. So if you're trying to elide the return from a value parameter, then the storage for the value parameter must also be the output storage itself. But remember: it is the caller that provides that storage for both the parameter and the output. And therefore, to elide the output copy, the caller must construct the parameter directly into the output.

To do this, now the caller needs to know that the function it's calling will elide the return value, because it can only stick the parameter directly into the output if the parameter will be returned. That's not going to generally be possible at the compiler level, because the caller doesn't necessarily have the implementation of the function. If the function is inlined, then maybe it can work. But otherwise no.

Therefore, the C++ committee didn't bother to allow for the possibility.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...