vendredi 2 août 2019

Output different for the same instruction - move and copy ctor

Can someone please explain me what is really happening here, because I'm a bit confused.

Here is my code

{
public:
    MetaData (int size, const std::string& name)
        : _name( name )
        , _size( size )
    {
        std::cout << "Call of Metadata(int, string) ctor " << std::endl;
    }

    // copy constructor
    MetaData (const MetaData& other)
        : _name( other._name )
        , _size( other._size )
    {
        std::cout << "Call of MetaData(const MetaData&) copy ctor" << std::endl;
    }

    MetaData& operator= (const MetaData& other)        
    {           
        std::cout << "Call of MetaData& operator= (const MetaData&) ctor" << std::endl; 
        _size = other._size;
        _name = other._name;

        return *this;
    }
    // move constructor
    MetaData (MetaData&& other)
        : _name( std::move(other._name) )
        , _size( other._size )
    {
        std::cout << "Call of MetaData (MetaData&&) move ctor" << std::endl;
    }

    MetaData& operator= (MetaData&& other)
    {
        _size = other._size;
        _name = std::move(other._name);
    }

    std::string getName () const { return _name; }
    int getSize () const { return _size; }

    private:
    std::string _name;
    int _size;
};

class ArrayWrapper
{
public:
    // default constructor produces a moderately sized array
    ArrayWrapper () : _metadata( 64, "ArrayWrapper" )
    {
        std::cout << "Call of ArrayWrapper() default ctor " << std::endl;
    }

    ArrayWrapper (int n) : _metadata( n, "ArrayWrapper" )
    {
        std::cout << "Call of ArrayWrapper(int) default ctor " << std::endl;
    }

    // move constructor
    ArrayWrapper (ArrayWrapper&& other) : _metadata( std::move(other._metadata) )
    {   
        std::cout << "Call of ArrayWrapper (ArrayWrapper&&) move ctor" << std::endl;                
    }

     ArrayWrapper& operator= (ArrayWrapper&& other)       
    {   
        std::cout << "Call of ArrayWrapper& operator=(ArrayWrapper&&) assignement ctor" << std::endl;   

        _metadata = std::move(other._metadata);         
        return *this;
    }


    ArrayWrapper& operator= (const ArrayWrapper& other)        
    {   
        std::cout << "Call of ArrayWrapper& operator= (const ArrayWrapper&) assignement ctor" << std::endl; 
        _metadata = other._metadata ;

        return *this;
    }

    // copy constructor
    ArrayWrapper (const ArrayWrapper& other) : _metadata( other._metadata )
    {
        std::cout << "Call of ArrayWrapper (const ArrayWrapper&) copy ctor" << std::endl;        
    }


    ~ArrayWrapper ()
    {
        std::cout << "Delete of ArrayWrapper" <<std::endl;        
    }
private:    
    MetaData _metadata;
};

In the main I do some test:

int main()
{           
    std::vector<ArrayWrapper> v;
    v.push_back(ArrayWrapper());
    v.push_back(ArrayWrapper());

    return 0;
}

The first v.push_back(ArrayWrapper()) output:

Call of Metadata(int, string) ctor
Call of ArrayWrapper() default ctor
Call of MetaData (MetaData&&) move ctor
Call of ArrayWrapper (ArrayWrapper&&) move ctor
Delete of ArrayWrapper

what is for me the output I was expecting. And here is what is confusing me, I was expecting the second instruction to output exactly the same thing but here is what I get:

Call of Metadata(int, string) ctor
Call of ArrayWrapper() default ctor
Call of MetaData (MetaData&&) move ctor
Call of ArrayWrapper (ArrayWrapper&&) move ctor
Call of MetaData(const MetaData&) copy ctor
Call of ArrayWrapper (const ArrayWrapper&) copy ctor
Delete of ArrayWrapper

Why the copy ctor of ArrayWrapper is getting called whereas in the first instruction it does not ?

To me to the output for the second v.push_back(ArrayWrapper()) should have been:

Call of Metadata(int, string) ctor
Call of ArrayWrapper() default ctor
Call of MetaData (MetaData&&) move ctor
Call of ArrayWrapper (ArrayWrapper&&) move ctor
Delete of ArrayWrapper //to delete the temporary moved

What am I getting wrong ?

Aucun commentaire:

Enregistrer un commentaire