Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Contiguous storage containers and move semantics

How can a container be both contiguous and support move semantics at the same time?

An example with std::vector: When push_back() is called using std::move on an lvalue:

std::vector<MyClass> v;

MyClass obj;
MyClass obj2;

vt.push_back(std::move(obj));
vt.push_back(std::move(obj2));

obj and obj2 are not necessarily allocated next to each other in memory. Now as vector must have its elements in contiguous memory, how would move semantics work in this case? It seems to me that it must copy the obj2 to vector v's contiguous memory region (next to obj), otherwise the contiguosity requirement would not be satisfied. But that requires a copy, not a move. What is the difference between the above and this then?:

MyClass obj;
MyClass obj2;

vt.push_back(std::move(obj));
vt.push_back(obj2);
like image 800
user3771111 Avatar asked Mar 12 '26 08:03

user3771111


1 Answers

You just need to read a little bit more about move semantics :-)

Moving an object does not change the address of the object itself. It merely calls the move constructor (or assignment operator, etc. depending on context) of another instance of the object, which is passed the one that is to be moved.

In this example, the vector does create two MyClass objects within its internal storage, one per push_back. But for the first one, instead of calling the copy constructor and passing obj (via MyClass const&), it calls the move constructor and passes the rvalue reference (MyClass&&) to obj. It is then up to that constructor to move the contents of the obj object into the one inside the vector.

In other words, the objects themselves are being created in the vector, and its only their contents that are moved (what it means to 'move' an object is potentially different for each type, hence it's the move constructor's job to do the actual moving).

Note that even with std::move, the move constructor may not be called -- there may not be one, for example, or there may be one that isn't noexcept (in which case std::vector can't use it in all circumstances without violating its exception safety guarantees).

like image 152
Cameron Avatar answered Mar 17 '26 02:03

Cameron



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!