Why does copy elision make an exception for formal parameters?

前端 未结 2 1809
自闭症患者
自闭症患者 2021-01-24 10:55

Here is a complete program:

#include 
using std::cout;
using std::endl;
using std::move;

int count {0};  // global for monitoring


class Triple         


        
相关标签:
2条回答
  • 2021-01-24 11:22

    First of all, understand that RVO and NRVO are opportunities offered by the writers of the standard to writers of compilers. A given compiler is free to ignore the possibility of RVO or NRVO if it can't make it work, if it doesn't know if it can make it work, if the moon is full, etc.

    In this case, though, it's easy. The way (N)RVO is fundamentally implemented, is by constructing the return value directly into the memory occupied by the return value, or even the memory occupied by the variable which will be set to that return value.

    That is, the potential savings from (N)RVO come not just from the ability to elide copy construction, but the ability to reduce copying in general.

    But when the source of the return value is a function parameter, it's too late for that. left is already somewhere in memory, and the return value has to go somewhere else. Short of some brute-force as-if-ruling from inlining, copying is already a given, because a second object has already been constructed.

    0 讨论(0)
  • 2021-01-24 11:31

    If copy elision is disabled, both cases consist of 1 copy followed by 3 moves. (Any output of 2 for your code would indicate a compiler bug).

    The copy is:

    • initialization of left

    and the moves are:

    • initialization of return value from left
    • initialization of temporary object denoted by a+b from return value
    • initialization of result from a+b

    It would be more illuminating to replace count with an output message saying "in copy constructor" and "in move constructor" . Currently you are not tracking moves at all.

    In the pass-by-reference case , all 3 moves can be elided. In the pass-by-value case, 2 of the moves can be elided. The move which cannot be elided is the move from left to the return value.

    I don't know the rationale for why this move can't be elided. Maybe it'd be difficult for a compiler to do something like A a = foo( A() ); if A() were elidable all the way up to a.

    0 讨论(0)
提交回复
热议问题