jeudi 1 avril 2021

Rules for default / user defined move / copy constructors to be called

I am trying to understand when default / user defined move / copy constructors will be called in case of containers objects :

#include <iostream>


//Rules for Eligible copy / move constructor  A copy / move constructor is eligible if it is not deleted.
//Every object should be either only copyable / moveable or both movable and copyable
//immovable objects really should also be non-copyable
struct nonmovable_1
{
    nonmovable_1() = default;
    //if there is no user defined move / copy / copy or move assignment operator constructor compiler creates default move constructor
    //If no user-defined copy constructor is provided then compiler will create a defult copy constructor
    /*nonmovable_1(const nonmovable_1&)
    {
        std::cerr << "nonmovable_1 copy" << std::endl;
    }*/
    nonmovable_1(const nonmovable_1&) = delete;
    nonmovable_1(const nonmovable_1&&)
    {
        std::cerr << "nonmovable_1 move" << std::flush << std::endl;
    }
    //nonmovable_1(nonmovable_1&&) = delete;
};
struct nonmovable_2
{
    nonmovable_2() = default;

    nonmovable_2(const nonmovable_2&)
    {
        std::cerr << "nonmovable_2 copy" << std::flush << std::endl;
    }
    //move constructor of nonmovable_2 is not declared
    //nonmovable_2(nonmovable_2&&) = delete;
};
struct movable
{
    movable() = default;

    movable(const movable&)
    {
        std::cerr << "movable copy" << std::flush << std::endl;
    }
    movable(movable&&)
    {
        std::cerr << "movable move" << std::flush << std::endl;
    }
};

struct is_movable
{
    movable    a;
    nonmovable_1 nm1;
    nonmovable_2 nm2;
    is_movable() = default;
    is_movable(const is_movable&)
    {
        std::cerr << "is_movable copy" << std::flush << std::endl;
    }
    //is_movable(is_movable&&) move constructor will be a deleted , if delete'd in a member
    is_movable(is_movable&&)
    {
        std::cerr << "is_movable move" << std::flush << std::endl;
    }
};


int main()
{
    //the copy constructor is actually called, because the move constructor of has_nonmovable is deleted
    //is_movable c;
    //is_movable d1(std::move(c));
    is_movable d1(is_movable{});
    is_movable d2(std::move(is_movable{}));
    // has_nonmovable_2 c2;
    //has_nonmovable_2 d2(std::move(c2));//the move constructor would be used for movable  copy constructor would be used for nonmovable_2
}

But the output is nothing when d1 object is created and 'is_movable move' for d2 object construction. I am failing to understand why move constructor of movable / nonmovable_1 objects not getting called?

Please let me know the rules when default / user defined move / copy constructors to be called?

Aucun commentaire:

Enregistrer un commentaire