2

I have read the below post which gives a very good insight into move semantics:

Can someone please explain move semantics to me?

but I am still fail to understand following things regarding move semantics -

  1. Does copy elision and RVO would still work for classes without move constructors?

  2. Even if our classes doesn't have move constructors, but STL containers has one. For operation like

std::vector vt = CreateMyClassVector();

and to perform operations like sorting etc. Why can't STL internally leverage move semantics to improve such operations internally using operations like copy elision or RVO which doesn't require move constructors?

3. Do we get benefited by move semantics in below case -

std::vector< int > vt1(1000000, 5); // Create and initialize 1 million entries with value 5

std::vector< int > vt2(std::move(vt1)); // move vt1 to vt2

as integer is a primitive type, moving integer elements will not offer any advantage. or here after move operation vt2 simply points to vt1 memory in heap and vt1 is set to null. what is actually happening? If latter is the case then even point 2 holds that we may not need move constructor for our classes.

4. When a push_back() is called using std::move on lvalue for e.g :

    std::vector<MyClass> vt;

    for(int i=0; i<10; ++i)
    {
        vt.push_back(MyClass());
    }

    MyClass obj;

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

now as vector has contiguous memory allocation, and obj is defined somewhere else in memory how would move semantics move the obj memory to vector vt contiguous memory region, wouldn't moving memory in this case is as good as copying memory, how does move justifies vectors contiguous memory requirements by simply moving a pointer pointing to a memory in different region of a heap.?

Thanks for explanation in advance! [EDITED the question as requested.]

Community
  • 1
  • 1
Goku
  • 43
  • 6
  • If you are using pointers, there's no need to use `move`. You can just do `.push_back(obj_ptr); obj_ptr = nullptr;` Move semantics are used when working on objects themselves. – Bartek Banachewicz Jan 30 '13 at 12:10
  • Thanks Bartek, I realized and edited the question, though class MyClass may have dynamic memory allocations. – Goku Jan 30 '13 at 12:16
  • 1
    Also, commas are not used to end sentences; please use some periods. – Nicol Bolas Jan 30 '13 at 12:18
  • Okay, then again: if Obj is a POD, it's exactly as you say - it has to be copied. But imagine that the only contents of the object are the pointer to buffer and its size. Only these two would be copied with move, whereas to perform full copy you would have to copy the buffer contents. – Bartek Banachewicz Jan 30 '13 at 12:19
  • but wouldn't the pointer to buffer falls at different memory address and just moving it may not meet contigous memory requirements for all elements of vector ? – Goku Jan 30 '13 at 12:29
  • Of the questions asked, Only point 3 is explained in duplicate Question(though it's a great post) linked. I still do not understand following - a) how does move justifies vectors contiguous memory requirements by simply moving a pointer pointing to a memory in different region of a heap. b) even if our classes doesn't have move constructors, but STL containers has one. For operation like std::vector vt = CreateMyClassVector(); and to perform operations like sorting etc. Why can't STL internally leverage move semantics to improve such operations ? – Goku Jan 31 '13 at 05:28

1 Answers1

3

Most semantics is not a way of moving memory. It's all about the transference of ownership of objects from one object instance to another. When you do this:

std::string str1("Some string.");
std::string str2(std::move(str1));

std::string allocates and manages a buffer of characters. Therefore, each std::string owns a buffer of memory, which contains the string itself.

The move constructor called to construct str2 will take the character buffer allocated by str1 and remove it from that object. Thus str2 now has the pointer that str1 originally allocated, and str1 doesn't have that pointer anymore. That's what move semantics is all about: transferring ownership of memory owned by an object.

If your class does not have a move constructor, std::vector will not call it. Obviously. Therefore, it cannot take advantage of any potential optimizations that having a move constructor might bring. But these optimization opportunities only exist for objects which have value semantics and which contain resources that must be managed. Otherwise, movement doesn't help you.

The general rule is to use smart pointers and container objects like vector, string, and the like to avoid having to write move constructors at all. Thus, (if your compiler properly supports generating move constructors) resource management happens automatically.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
  • Thanks, Yes my class doesn't have move constructors, but STL containers has one. so say when I copy a vector vt filled with MyClass objects into another vector vt2 or perform operations like sorting etc. Wouldn't STL internally leverage move semantics to improve such operations ?. Also in last paragraph you mentioned general rule of thumb is to use smart pointers and STL containers but if they contain user defined types without move constructor then as you mentioned they may not get benefited isn't it ?. – Goku Jan 30 '13 at 12:42
  • @Goku: No, because you're copying the vector. The vector will allocate a new buffer and copy every one of its objects into the second vector. IF the vector were a temporary (like the return value of an expression, or in the case of `v2 = std::move(v1)`) then the STL would leverage by moving the entire buffer from `v1` to `v2`, leaving `v1` empty. – Laurent LA RIZZA Feb 19 '14 at 16:44