简体   繁体   中英

Move semantics on individual vector elements

What is the behavior of a std::move on an individual vector element? eg (grossly simplified code follows)

Will this do the proper move and do I need to erase() the moved element?

I normally use a copy constructor and a delete, will the compiler optimize for a move (synthesized) instead of using a copy constructor in some cases?

I tried using smart-pointer wrappers and didn't see a significant speedup. Move semantics look like what I want to use.

template< class T >
class Foo
{
};

vector< Foo< T > > v1, v2;

v2.emplace_back( std::move( v1[ 2 ] );

I don't see significant speedup using move operations and I think I've implemented the move constructor and move assignment operator correctly.

Please shed some light on this problem.

Move semantics have two jobs:

  • Indicate that ownership of a resource (such as some allocated memory, or a FILE* pointer, or a stream) changed hands
  • Avoid unnecessary copies in the above cases.

For example, let's say we have a vector:

vector<int> a; 
for(int i = 0; i < 10000; i++) { 
    a.push_back(i); 
}

If I write:

vector<int> b = a;

This makes a copy of every single element in a , so it's a slow operation. However, if I write

vector<int> b = std::move(a); 

None of the elements in a are copied, and this ends up being a lot faster. However, a no longer owns those elements. We can demonstrate it using the below code:

#include <vector>
#include <iostream>

int main() {
    using std::vector;

    vector<int> a = {1, 2, 3};
    vector<int> b = std::move(a); 
    if(a.data() == nullptr) // This should be true now
        std::cout << "a.data() is null now\n"; 
    if(a.size() == 0)
        std::cout << "a.size() is zero now\n"; 
}

On my system, using gcc and clang, this code prints

a.data() is null now
a.size() is zero now

This applies even if you have a wrapper class:

#include <vector>
#include <iostream>

template<class T>
class Wrapper {
   public:
    // Because all the members of Wrapper are public,
    // the compiler automatically generates move and copy constructors
    T value; 
};


int main() {
    using std::vector;

    Wrapper<vector<int>> a = {{1, 2, 3}};
    Wrapper<vector<int>> b = std::move(a); 
    // Same output as before
    if(a.value.data() == nullptr)
        std::cout << "a.data() is null now\n"; 
    if(a.value.size() == 0)
        std::cout << "a.size() is zero now\n"; 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM