0

I understand copy elision well. But I can't find out what happens when copy elision is not possible. In those situations, if available, is the move constructor or move assignment operator guaranteed to be called? Are there any situations where moving will not be possible and the code will fallback to copy constructor or assignment?

class X {
  //A heavy class expensive to copy

  //Moving ctor
  X(X&& other) {
    //...
  }
  //Moving assignment op
  X& operator=(X&& other) {
      //...
        
      return *this;
  }
  //...
}

//Most compilers can't do copy elision
X test(int i) {
    X n1;
    X n2;
    
    if (i > 0) {
        return n1;
    } else {
        return n2;
    }
}

//What happens here?
int main() {
    //Is move construction guaranteed?
    X x1 = test(-1);

    X x2;
    //Is move assignment guaranteed?
    x2 = test(10);
    
    return 0;
}

My understanding, so far, is this.

  • Compiler first attempts to do copy and move elision.
  • If that's not possible then it tries to apply move constructor or move assignment if available.
  • Only if a move ctor or assignment is not available then it degrades down to using copying.

Is that accurate? I was looking for an authoritative source to confirm my observations.

RajV
  • 6,860
  • 8
  • 44
  • 62
  • 1
    Elision is an optimization; it says when a certain thing may not happen. If elision is not applied, then the particular "certain thing" that elision could have prevented will happen. Which that is depends on the situation. – Nicol Bolas Nov 28 '22 at 15:19
  • I think you may be confusing NVRO which is optional and RVO which is not optional since C++17. ie `return n1;` is NVRO which is optional. See also [Copy elision](https://en.cppreference.com/w/cpp/language/copy_elision). – Richard Critten Nov 28 '22 at 15:20
  • @RichardCritten that's possible. But I am asking what happens when either RVO or NRVO is not possible. Does the compiler always try to use move? Let me know if the question needs more clarity. Thanks. – RajV Nov 28 '22 at 15:22
  • @NathanOliver: The problem is that this is a duplicate of *parts of* like 3 or 4 questions. – Nicol Bolas Nov 28 '22 at 15:23
  • `RVO` since C+17 is not an optional optimization so it always must be possible. Regarding clarity - I think question is fine. If possible pick before or after C++17 to avoid a major Standard change in this area. – Richard Critten Nov 28 '22 at 15:23
  • @NathanOliver I read that question a few times before posting. It says move will be attempted if NRVO is not possible. But doesn't cite any specs. I was looking for a more official answer. – RajV Nov 28 '22 at 15:29
  • @RajV: I'm not sure what "cite any specs" would do other than add confusion. Your overall problem seems to be that you don't know what the code means in the *absence* of elision. Spec citations would just make everything more complex. But if you do want spec citations, you should add the language-lawyer tag. – Nicol Bolas Nov 28 '22 at 15:31
  • @RajV If you want quotes from official documentation then you should tag the Q with the `language-lawyer` tag. – NathanOliver Nov 28 '22 at 15:38
  • That said, this looks like it should work as a dupe as it has the official text: https://stackoverflow.com/questions/17473753/c11-return-value-optimization-or-move – NathanOliver Nov 28 '22 at 15:40
  • 1
    @RajV This may be the part of the standard you are looking for: https://timsong-cpp.github.io/cppwp/n4868/class#copy.elision-3. Note that in different C++ standards (versions), the wording is different, but the meaning is generally the same. – Daniel Langr Nov 28 '22 at 15:40
  • @NathanOliver I don't think that answer has (all) the official text OP is looking for. This text is about copy elision, but it does not imply that the move constructor will be considered first for initialization of the return value. IMO, the rule that specifies this is completely orthogonal to copy elision rules. – Daniel Langr Nov 28 '22 at 15:59
  • 1
    The link posted by @DanielLangr has what I was looking for. Here's the same document from from isocpp: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/n4910.pdf. Section "11.9.6 Copy/move elision" says "a move operation is first considered before attempting a copy operation" – RajV Nov 28 '22 at 16:05
  • @RajV Note that in the current draft, the specification changed again: http://eel.is/c++draft/expr.prim.id.unqual#3.sentence-6 and http://eel.is/c++draft/expr.prim.id.unqual#4. It is now even in a different chapter. – Daniel Langr Nov 28 '22 at 16:29

0 Answers0