9

I have a simple class which contains an std::vector, and I would like to benefit from move semantics (not RVO) when returning the class by value.

I implemented the move constructor, copy constructor and copy assignment operators in the following way:

class A { public: // MOVE-constructor. A(A&& other) : data(std::move(other.data)) { } // COPY-constructor. A(const A& other) : data(other.data) { } // COPY-ASSIGNMENT operator. A& operator= (const A& other); { if(this != &other) { data = other.data; } return *this; } private: std::vector<int> data; }; 

Are the above implementations correct?

And an other question: do I even have to implement any of these members, or are they auto-generated by the compiler? I know that the copy-constructor and the copy-assignment operator are generated by default, but can the compiler auto-generate the move constructor as well? (I compile this code both with MSVC and GCC.)

Thanks in advance for any suggestions. (I know that there already are some similar questions, but not for this exact scenario.)

10
  • 3
    In this instance, a move constructor will be generated automatically for you. So all this hard work is unncessary. Commented Jan 8, 2013 at 10:07
  • I put breakpoints into the copy- and the move-ctors to see which one is gettin called, and in certain scenarios the move-ctor is called. But if I comment out the move-ctor, then in the same situations the copy-ctor gets called. Doesn't this mean that the move-ctor is not generated by default? (on Windows with MSVC) Commented Jan 8, 2013 at 10:16
  • 2
    @Mark: A move-ctor is only generated if no user defined copy-ctor/assignment-op/dtor exists (because otherwise it would likely be wrong). Same goes for move-assignment. Commented Jan 8, 2013 at 10:17
  • 1
    @Mark Though unfortunately MSVC indeed doesn't automatically generate move operators. Commented Jan 8, 2013 at 11:27
  • 2
    @Mark: depends what you mean by "necessary". It's not necessary in C++11. Until MSVC implements this part of C++11, you might like to define it in your code, in order to get an optimization in MSVC that is automatic in C++11. You could call the language currently implemented by MSVC "MS-C++0x", in which case the move-ctor definition is necessary in MS-C++0x but not in C++11. Commented Jan 8, 2013 at 11:40

2 Answers 2

6

They're all unnecessary for this class[*], since it would have implicit ones if you didn't declare any of them.

Your constructors are fine. So the following code ostensibly calls the move constructor:

A f() { return A(); } A a = f(); // move construct (not copy construct) from the return value of f 

In fact move-elision might kick in, in which case only the no-args constructor is actually called. I assume you plan to provide some constructors other than copy and move ;-)

Your copy assignment is fine, it differs from the implicit one only in that it has the self-assignment check, which the implicit one would not. I don't think we should have the argument whether a self-assignment check is worth it or not, it's not incorrect.

You haven't defined a move-assignment operator. Given that you defined the others, you should have done, but if you get rid of the rest it's implicit[*]. The move assignment operator (whether user-defined or implicit) is what ensures that the following code will move instead of copying:

A a; a = f(); 

[*] On a completed C++11 implementation, of which so far none exist. You can check on a per-compiler basis whether this feature is implemented yet, and probably you'll end up with some horrible #define shenanigans until MSVC does.

Sign up to request clarification or add additional context in comments.

1 Comment

Oh, then I misunderstood the term RVO, thanks for clearing that up. I changed it in the original question to "move semantics", that is correct I guess.
2

For this exact scenario, You don't need to declare any move/copy/assignment functions. Compiler will generate correct defaults.

2 Comments

Are there exactly defined rules about when the compiler can correctly generate them and when it can't?
@Mark: yes, in chapter 12 of C++11. For example 12.8/9 says exactly when there's a synthesized move constructor (you then need to look up all the technical terms used in that list, in order to understand it!).

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.