Search code examples
c++move-semanticsrvalue-referencervalue

why non-movable Object still a copy


Consider the following code, Entity object is non-movable. I know that std::move(Obj) just cast the Obj to a rvalue reference Obj. And I also know that rvalue reference variable is still a lvalue object. But I still confusing why statement auto temp = std::move(a) can call copy constructor, statement a = std::move(b); can call copy assignment operator. Since, std::move(a) is a rvalue reference, why it can still call lvalue constructor.

#include <iostream>

template<typename T>
void my_swap(T& a, T& b) {
    auto temp = std::move(a);
    a = std::move(b);
    b = std::move(temp);
}

class Entity{
    int _id;
public:
    Entity(int id) :_id(id)  {std::cout << "construtor\n" << std::endl;}
    Entity(const Entity& other) {
        _id = other._id;
        std::cout << "copy constructor\n" << std::endl;
    }

    Entity& operator= (const Entity& other) {
        if (&other == this) return *this;
        this->_id = other._id;
        std::cout << "copy assignment operator\n";
        return *this;
    }

};

int main() {
    Entity e1 = Entity(10);
    Entity e2 = Entity(20);
    my_swap(e1,e2);
    return 0;
}


Solution

  • Entity object is non-movable

    No. Even it doesn't have move constructor/assignment-operator, it has copy constructor/assignment-operator taking lvalue-reference to const. std::move(a) and std::move(b) are rvalue (xvalue) expressions and they could be bound to lvalue-reference to const.

    You might also check std::is_move_constructible:

    Types without a move constructor, but with a copy constructor that accepts const T& arguments, satisfy std::is_move_constructible.