How can I pass a std::unique_ptr
into a function? Lets say I have the following class:
class A
{
public:
A(int val)
{
_val = val
As MyFunc
doesn't take ownership, it would be better to have:
void MyFunc(const A* arg)
{
assert(arg != nullptr); // or throw ?
cout << arg->GetVal() << endl;
}
or better
void MyFunc(const A& arg)
{
cout << arg.GetVal() << endl;
}
If you really want to take ownership, you have to move your resource:
std::unique_ptr<A> ptr = std::make_unique<A>(1234);
MyFunc(std::move(ptr));
or pass directly a r-value reference:
MyFunc(std::make_unique<A>(1234));
std::unique_ptr
doesn't have copy on purpose to guaranty to have only one owner.
There's basically two options here:
void MyFunc(unique_ptr<A> & arg)
{
cout << arg->GetVal() << endl;
}
int main(int argc, char* argv[])
{
unique_ptr<A> ptr = unique_ptr<A>(new A(1234));
MyFunc(ptr);
}
Note that in this case, the assertion will hold!
void MyFunc(unique_ptr<A> arg)
{
cout << arg->GetVal() << endl;
}
int main(int argc, char* argv[])
{
unique_ptr<A> ptr = unique_ptr<A>(new A(1234));
MyFunc(move(ptr));
assert(ptr == nullptr)
}
Since unique_ptr
is for unique ownership, if you want to pass it as argument try
MyFunc(move(ptr));
But after that the state of ptr
in main
will be nullptr
.
Passing std::unique_ptr<T>
as value to a function is not working because, as you guys mention, unique_ptr
is not copyable.
What about this?
std::unique_ptr<T> getSomething()
{
auto ptr = std::make_unique<T>();
return ptr;
}
this code is working
Why can I not pass a
unique_ptr
into a function?
You cannot do that because unique_ptr
has a move constructor but not a copy constructor. According to the standard, when a move constructor is defined but a copy constructor is not defined, the copy constructor is deleted.
12.8 Copying and moving class objects
...
7 If the class definition does not explicitly declare a copy constructor, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted;
You can pass the unique_ptr
to the function by using:
void MyFunc(std::unique_ptr<A>& arg)
{
cout << arg->GetVal() << endl;
}
and use it like you have:
or
void MyFunc(std::unique_ptr<A> arg)
{
cout << arg->GetVal() << endl;
}
and use it like:
std::unique_ptr<A> ptr = std::unique_ptr<A>(new A(1234));
MyFunc(std::move(ptr));
Important Note
Please note that if you use the second method, ptr
does not have ownership of the pointer after the call to std::move(ptr)
returns.
void MyFunc(std::unique_ptr<A>&& arg)
would have the same effect as void MyFunc(std::unique_ptr<A>& arg)
since both are references.
In the first case, ptr
still has ownership of the pointer after the call to MyFunc
.
Why can I not pass a
unique_ptr
into a function?
You can, but not by copy - because std::unique_ptr<>
is not copy-constructible.
Surely this is the primary purpose of the construct?
Among other things, std::unique_ptr<>
is designed to unequivocally mark unique ownership (as opposed to std::shared_ptr<>
).
And most strangely of all, why is this an OK way of passing it?
Because in that case, there is no copy-construction.