0

I am trying to understand C++ move semantics, std::move() and rvalue references.

I've implemented this example.

#include <iostream> #include <vector> int main() { int totalSize = 6; std::vector<double> oldData{ 10, 20, 30 }; oldData.resize(totalSize, 0); std::vector<double> newData(std::move(oldData)); return 0; } 

I'd like to know is this actually moving vector oldData to newData or is copying happening under the hood.

3
  • 4
    The move is fine, but think about your loop condition - oldData.size() keeps changing. Commented Mar 25, 2019 at 9:08
  • 1
    how you populate the vector has nothing to do with the ctor and the move. That is just noise that distracts you. Commented Mar 25, 2019 at 9:17
  • I concur with the previous comments about your example. A simple call to std::vector::resize will do exactly what you set out to do with the reserve and loop, only without a bug. Commented Mar 25, 2019 at 9:24

1 Answer 1

1

Assuming you fix the infinite loop at:

 for(unsigned i = 0; i < totalSize - oldData.size(); ++i) oldData.push_back(0); 

And write something like:

 for(unsigned i = oldData.size(); i < totalSize; ++i) oldData.push_back(0); 

or, even better:

 oldData.resize(totalSize, 0); 

Then std::move will move all the data from oldData to newData. Here is a quote from cppreference:

6) Move constructor. Constructs the container with the contents of other using move semantics. Allocator is obtained by move-construction from the allocator belonging to other. After the move, other is guaranteed to be empty().

7) Allocator-extended move constructor. Using alloc as the allocator for the new container, moving the contents from other; if alloc != other.get_allocator(), this results in an element-wise move. (in that case, other is not guaranteed to be empty after the move)

In your specific case, the vector has a default allocator, which means that only item (6) applies. However, if someone passes an allocator then things become more interesting.

Here is the rest of cppreference on the subject of complexity:

6) Constant.

7) Linear if alloc != other.get_allocator(), otherwise constant.

Again, in your case the complexity is O(1), but with allocators things get more interesting.

Conclusion: internal representation has to move a constant number of pointers in O(1), and not move the elements one-by-one. It is possible to implement vector with one pointer with capacity and size integers, or three pointers (begin, end, and the end of capacity). And for all these implementations, moving is a simple playing around with pointers.

However, if a non-default allocator is provided and the two vectors use a different allocator object, then the values have to be moved or copied one-by-one.

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.