Search code examples
c++pass-by-valuecopy-elision

Will any compiler actually ever elide these copies?


Given

struct Range{
    Range(double from, double to) : from(from), to(to) {}
    double from;
    double to;
    // if it matters to the compiler, we can add more fields here to make copying expensive
};

struct Box{
    Box(Range x, Range y) : x(x), y(y) {}
    Range x;
    Range y;
};

someone said that in Box box(Range(0.0,1.0),Range(0.0,2.0)), the compiler can avoid copying Range objects altogether by constructing them inside box to begin with.

Does any compiler actually do this?

My own attempts haven't succeeded.


Solution

  • The compiler can - and normally does - elide the copies from the temporary to the argument. The compiler cannot elide the copy from the argument to members. While it may technically possible to elide these copies in some cases, the relevant permission isn't given. The section of the standard is 12.8 [class.copy] paragraph 31 which spells out 4 situations where a copy can be elided (the exact rules are a bit non-trivial):

    1. When returning a named, function local variable using it name.
    2. When using a named, function local variable in a throw expression.
    3. When copying a temporary object.
    4. When catching an exception by value.

    Passing a named argument as parameter to the construction of a member variable is, clearly, none of these situations.

    The essential background of the rules for copy elision is that in some contexts the declaration of functions suffice to determine when an object will be used. If it is clear upon construction time where the object can be constructed, it can be elided. The caller of a constructor cannot determine based only on the declaration of the constructor where the object will be used.