klaus
klaus

Reputation: 826

copy-constructor called instead of move-constructor

I have the following class :

class Component {
  public:
    // Constructor
    explicit Component(const void* data, size_t size)
      : _size(size),
        _data(new int[_size]) {
          (void)memcpy(_data, data, _size);
    }

    // Destructor
    ~Component() {
      delete[] _data;
    }

    // Copy-ctor.
    Component(const Component& o)
      : _size(o._size),
        _data(new uint8_t[_size]) {
     (void)memcpy(_data, o._data, _size);
   }

   // Assignment operator
   Component& operator=(const Component& o) {
     if (this != &o) {
       delete[] _data;
       _size = o.getSize();
       _data = new uint8_t[_size];
       (void)memcpy(_data, o.getData(), _size);
     }
     return *this;
   }

   // Move-constructor
   Component(Component&& o)
     : _size(o._size),
       _data(o._data) {
     o._data = nullptr;
   }

   // Move assignment
   Component& operator=(Component&& o) {
     if (this != &o) {
       delete[] _data;
       _size = o._size;
       _data = o._data;
       o._data = nullptr;
     }
     return *this;
   }

   private:
    size_t _size;
    int _data;
};

I would like to test my move-constructor. So I tried to do :

void f(Component&& c) {
  Component c2 = c; // Expect to use move-constructor
}
int data[] = { 0, 1 };
Component c{&data[0], sizeof(data)};
f(std::move(c)); // getting a rvalue reference from lvalue reference

But then I saw that it was my copy-constructor that was called and not the move-constructor. Do you have any idea why ?

Upvotes: 1

Views: 1359

Answers (2)

Ben Voigt
Ben Voigt

Reputation: 283893

In this code

void f(Component&& c)
{
    Component c2 = c; // Expect to use move-constructor
}

c is an lvalue. That's what lets you use it more than one time inside of f.

The && parameter is an indication that the caller will not need the object any longer and you are free to loot it. But now your function is conceptually the owner... subroutines that you call should not loot your object unless you give them permission in turn.

Making c an rvalue would break many usecases, for example:

void f(string&& s)
{
    string inputfilename = s + ".in";
    string outputfilename = s + ".out";
    // use s in some other ways
}

To give subroutines permission to loot your parameter, you use std::move.

Upvotes: 3

Hassia Biker
Hassia Biker

Reputation: 96

It looks like you need to change f to

void f(Component&& c) {
    Component c2 = std::move(c);
}

And call it like:

f(c);

Please see: similar example

NOTE: I haven't tested it, but please see answers to the other thread for an explanation.

Upvotes: 1

Related Questions