The following is toy code I am trying... I understand the first and second one. The first one give the ownership to _p
. The second one copies p
to _p
. but I don't understand the third one...
What does std::move
of const shared_ptr &
mean? Thank you.
class P { };
class A {
public:
// first one
A(std::shared_ptr<P> &p, int) : _p(std::move(p))
{
std::cout << "1st Ctor: "
<< p.use_count() << ", " << _p.use_count() << std::endl;
}
// second one
A(const std::shared_ptr<P> &p, std::string) : _p(p)
{
std::cout << "2nd Ctor: "
<< p.use_count() << ", " << _p.use_count() << std::endl;
}
// third one
A(const std::shared_ptr<P> &p) : _p(std::move(p))
{
std::cout << "3rd Ctor: "
<< p.use_count() << ", " << _p.use_count() << std::endl;
}
private:
std::shared_ptr<P> _p;
};
int main()
{
{
std::shared_ptr<P> p = std::make_shared<P>();
A a(p, 1);
std::cout << "1. body: " << p.use_count() << std::endl;
}
std::cout << "-------------" << std::endl;
{
std::shared_ptr<P> p = std::make_shared<P>();
A a(p, "2");
std::cout << "2. body: " << p.use_count() << std::endl;
}
std::cout << "-------------" << std::endl;
{
std::shared_ptr<P> p = std::make_shared<P>();
A a(p);
std::cout << "3. body: " << p.use_count() << std::endl;
}
}
Result is:
$ ./a.out
1st Ctor: 0, 1
1. body: 0
-------------
2nd Ctor: 2, 2
2. body: 2
-------------
3rd Ctor: 2, 2
3. body: 2
(updated: adding comment to clarify which one is first one, second one, etc.)
std::move
just performs conversion and produces xvalue (rvalue).
When being passed a const std::shared_ptr<P>
, its return type would be const std::shared_ptr<P>&&
. Then for _p(std::move(p))
the copy constructor of std::shared_ptr
(but not move constructor which taking rvalue-reference to non-const ) will be called, the effect is just same as the 2nd case.
Basically move operation tends to perform modification on the object being moved; it's not supposed to work on const
objects.
std::move
is a function which converts the argument to an rvalue reference. The function call is an xvalue expression.
When the argument is a reference to const, then the result of the conversion is an rvalue to const. If you initialise from rvalue to const, copy constructor will be used because the rvalue reference parameter to non-const of the move constructor cannot bind to rvalue reference argument to const.
I think there is also an implicit question by OP of how
_p(std::move(p))
might differ from_p(p)
_p(std::move(p))
doesn't differ from _p(p)
in case of const std::shared_ptr<T>
.
In theory, if decltype(_p)
was a type that had a constructor T(const T&&)
, then there would be a difference, since that constructor would be invoked by _p(std::move(p))
but not by _p(p)
. Such constructor would be quite unconventional, but technically well-formed. std::shared_ptr
doesn't have such constructor.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.