Search code examples
c++c++11move

std::move on a C++ class does not move all members?


I understand that using v.push_back(std::move(foo)) will move foo contents to a vector.
However I do not understand why the below code :

#include <iostream>
#include <vector>

struct Foo {
    std::string s;
    float       f;
    friend std::ostream& operator<<(std::ostream& stream,const Foo& foo) {
        stream << "{" << foo.s << ":" << foo.f << "}";
        return stream;
    }
};


int main() {
    Foo foo{"Hello",2.0f};
    std::vector<Foo> v;
    v.push_back(foo);
    std::cout << foo << std::endl;
    v.push_back(std::move(foo));
    std::cout << foo << std::endl;
    std::cout << v[0] << v[1] << std::endl;
}

produces this output :

{Hello:2}
{:2}
{Hello:2}{Hello:2}

Why 2 is not "moved" ?


Solution

  • You create a variable foo

    Foo foo{"Hello",2.0f};
    

    Then declare a vector

    std::vector<Foo> v;
    

    Then call push_back which invokes a copy of your Foo

    v.push_back(foo);
    std::cout << foo << std::endl;
    

    Then you std::move(foo), which invalidates your foo instance

    v.push_back(std::move(foo));
    

    Trying to cout foo is now undefined behavior, as the internals are may be garbage.

    std::cout << foo << std::endl;
    

    While you technically could std::move a primitive, most implementations will simply invoke a copy because it is cheaper and faster.