mytype foo() {
mytype one;
...
if(something) {
mytype two;
...
return two;
}
return one;
}
Is going to be much harder because you don't know are compile time which is returned and so cannot construct the one you return in the correct place. That is just off the top of my head, I'm not a compiler writer, I'm sure they have figured out the simple versions of the above, but you can start to see the complex versions that they can't.I'm not too confident on that last part, because such an implementation would mess with semantics in case of an exception, so anyone feel free to correct me on that.
This sounds wrong, are you sure? Would you mind demonstrating with an example on godbolt? Whether NRVO applies or not, the ABI should be the same, AFAIK.
In RVO there is no problem because you know what object is the one you need to put there.
In NRVO there is a problem because you might have one of multiple objects being returned and you need to know which one to construct at the call site; it can't be all of them on top of each other. But you don't necessarily know at the time of construction whether that object will be the one that is actually returned. Doing so requires imperfect code analysis so the standard would need to define the complicated analyses to perform.
NRVO requires the compiler to analyze the flow, like if 2 different variables/constructions can lead to the return (what one do we take, or can we do either later?).
Also, with RVO it's easy to detect and elide destruction calling for things going out of scope whilst NRVO would require more careful management of destruction order,etc.
Basically, NRVO touches a lot of things in "inconventient" places that can easily require reworking internal compiler structures to track destinations whilst RVO was probably far easier to just "hack in".
Maybe it's the guaranteed elision that makes it a problem, like you can't fail the analysis, but then maybe you go the rust route - fail to compile and urge the programmer to rewrite their code so it accepts it.
Make it opt in with [[must_elide]] so old code still works I guess.
I recall reading that at a high level RVO is implemented by treating the return value as an external object. In simple terms (simplistic terms) RVO then works by
- first instantiating the return variable,
- passing the var by reference to the function,
- and then use return value to actually initialize the variable passed by reference.
The moment there's some funny logic on what to write to that output value, the problem gets far more complex.
hn45e7pbij•1d ago
dalvrosa•1d ago
pdpi•42m ago
sprocketz•39m ago
bluGill•32m ago