I am trying to write a move constructor for a structure but I can't understand why I fail to call the move constructor of structure member:
#include <memory>
struct C
{
std::unique_ptr<int[]> mVector;
size_t mSize;
C() = default;
C(C &&temp)
: mVector(temp.mVector)
, mSize(temp.mSize)
{}
};
When I compile this I get:
gcc -c TempTest.cpp
TempTest.cpp: In constructor 'C::C(C&&)':
TempTest.cpp:9:23: error: use of deleted function 'std::unique_ptr<_Tp [], _Dp>::unique_ptr(const std::unique_ptr<_Tp [], _Dp>&) [with _Tp = int; _Dp = std::default_delete<int []>]'
9 | , mSize(temp.mSize)
| ^
In file included from c:/msys64/mingw64/include/c++/10.3.0/memory:83,
from TempTest.cpp:1:
c:/msys64/mingw64/include/c++/10.3.0/bits/unique_ptr.h:723:7: note: declared here
723 | unique_ptr(const unique_ptr&) = delete;
| ^~~~~~~~~~
Because in contructor temp
is a rvalue reference, it is non-const so temp.mVector
should be non-const and should call the unique_ptr
move constructor but instead it calls the copy constructor which is deleted. Any idea where is the error?
Why rvalue reference member would be const?
Don't assume that it's const
. You should assume that unique_ptr(const unique_ptr&)
is merely the best match, from the available constructors.
Because in constructor
temp
is a rvalue reference
Surprise! It is not an r-value reference.
The variable temp
is bound to an r-value, when the constructor is called. And now that it's a named variable, it's no longer a "temporary". It has become an l-value.
Since you know that the value was an r-value when the constructor was called, you can safely move the members, converting them back to an r-value.
C(C &&temp)
: mVector(std::move(temp.mVector))
// ^^^^^^^^^ We know that temp CAME FROM an r-value,
// so it can safely be moved.
, mSize(temp.mSize)
{}