mardi 31 août 2021

I don't understand this behavior with move constructors [duplicate]

I'm new with C++11. I wrote this class to help me to well understand move behavior in the classes.

class MoveChecker
{
    private:
        bool wasMoved;
        int something;
    public:
        MoveChecker() : wasMoved(false), something(0) {}
        MoveChecker(int data) : wasMoved(false), something(data) {}
        MoveChecker(MoveChecker const& m) : wasMoved(false), something(m.something) {}
        MoveChecker(MoveChecker&& m) noexcept : wasMoved(true), something(m.something) {}
        ~MoveChecker() noexcept {} 
        void swap(MoveChecker& m) noexcept
        {
            std::swap(this->wasMoved, m.wasMoved);
            std::swap(this->something, m.something);
        }
        MoveChecker& operator=(MoveChecker const& m)
        {
            MoveChecker(m).swap(*this);
            return *this;
        }
        MoveChecker& operator=(MoveChecker&& m) noexcept
        {
            MoveChecker(std::move(m)).swap(*this);
            return *this;
        }
        bool moved() const noexcept { return this->wasMoved; }
        int value() const noexcept { return this->something; }
};
void swap(MoveChecker& m1, MoveChecker& m2) noexcept { m1.swap(m2); }

Then, I play with a template container, and I check it with my MoveChecker class. Here is a simplified version.

template <typename T>
class Container
{
    private:
        T data;
    public:
        Container() : data() {}
        Container(T const& data_) : data(data_) {}
        Container(T&& data_) noexcept : data(std::move(data_)) {}
        Container(Container<T> const& c) : data(c.data) {}
        Container(Container<T>&& c) noexcept : data(std::move(c.data)) {}
        ~Container() noexcept {}
        void swap(Container<T>& c) noexcept
        {
            using std::swap;
            swap(this->data, c.data);
        }
        Container<T>& operator=(Container<T> const& c)
        {
            Container<T>(c).swap(*this);
            return *this;
        }
        Container<T>& operator=(Container<T>&& c) noexcept
        {
            Container<T>(std::move(c)).swap(*this);
            return *this;
        }
        T const& getData() const noexcept { return this->data; }
};

When I use this container, I have a behavior I can't explain. See the following main code:

int main()
{
    MoveChecker mc(123);

    Container<MoveChecker> c1_(mc);
    Container<MoveChecker> c1(std::move(c1_));
    std::cout << "c1.getData().moved() = " << c1.getData().moved() << std::endl;

    Container<MoveChecker> c2 = Container<MoveChecker>(mc);
    std::cout << "c2.getData().moved() = " << c2.getData().moved() << std::endl;
    
    Container<MoveChecker> c3 = std::move(Container<MoveChecker>(mc));
    std::cout << "c3.getData().moved() = " << c3.getData().moved() << std::endl;

    return 0;
}

The output of execution of this code is the following:

c1.getData().moved() = 1
c2.getData().moved() = 0
c3.getData().moved() = 1

In my opinion, it means that Container<MoveChecker>(mc) given to build c2 is not considered as a temporary variable. Why ? Did I something wrong or is it the expected behavior ?

System: openSUSE (Linux)

Compiler used: gcc 4.8.5

Compilation command: g++ move.cpp -o move.exe -std=c++11

Aucun commentaire:

Enregistrer un commentaire