1

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 ?

2

2 Answers 2

3

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.

Sign up to request clarification or add additional context in comments.

3 Comments

@klaus: No... it accepts an rvalue (prvalue or xvalue), but it is an lvalue.... up until the return statement, when all by-value and rvalue-reference parameters and locals become xvalues.
can you give link to c++ standard discussing above topic , i'd like to read more
@emaditaj: That would be eel.is/c++draft/basic.lval it is pretty long and complicated. The first example (actually a block of code containing multiple examples) ends with A&& ar = static_cast<A&&>(a); and the note, ar is an lvalue.
1

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.

2 Comments

You'd still need to call f(std::move(c))
Yes, it works but I do not understand why my solution does not work !

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.