About std::move
, here is what I can interpret, according to http://en.cppreference.com/w/cpp/utility/move :-
std::move
(or in rare case, std::forward
). std::move
is calling operator=(A&& other)
. operator=(A&&)
.operator=(A&&)
would be called. It need a special converter.xvalue
(the &&) : std::move
and std::forward
.After adding many of std::move(std::unique_ptr)
in my code, I start to worry that for such basic feature like transfer ownership, I have to heavily rely on the standard library (std::
).
Do I really have to use std::move
to transfer ownership?
Is spamming and hard-code calling std::move
in many places of code-base a correct way to go for a high-standard program?
Should std::move
be encapsulated?
They are actually a single question, but ask in different perspectives.
As request, here is my trial & error. It compiled ok.
I have no problem about the code, but I worry about its approach / pattern.
https://ideone.com/y8Pcgf
class T{
public: int value;
public: T(int a=1234){
value = a;
}
};
int main() {
std::unique_ptr<T> t1 = std::unique_ptr<T>(new T(1));
void* databaseNew=operator new [](sizeof(std::unique_ptr<T>));
std::unique_ptr<T>* t1ptr=static_cast<std::unique_ptr<T>*>(databaseNew);
new (t1ptr) std::unique_ptr<T>(std::move(t1));
return 0;
}
The need to explicitly move
, of which you complain, was actually done on purpose. Before unique_ptr
, STL had a horrid construct called auto_ptr
. It would move ownership impllicitly, and was borderline unusable unless you really really really knew what you were doing.
To make things more usable, in most cases C++ now requires you to explicitly state that you intend on moving ownership over a container, by using std::move
.
In fact, std::move
is little more than a cast to an rvalue reference.
There are cases where such an explicit specification is not necessary. For example, if the container from which you take ownership is already an rvalue (e.g. - a temporary object), then no case using std::move
is necessary. For example, the following doesn't compile:
std::unique_ptr<int> a;
a = new int;
But the following does, without needing a move:
std::unique_ptr<int> a;
a = std::unique_ptr<int>(new int);
The reason this does not need a call to std::move
, despite invoking the move operator, is that the object we move the ownership away from is already a temporary object (i.e. - an rvalue), so no cast is necessary.
Another example is if you call a function that returns a unique_ptr. You might have to call std::move
inside the function to get it into the return value, but you do not need to call std::move
on the function's return value to get it into the outside unique_ptr
. It is already an rvalue, and therefor no cast is necessary.