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_ptrinto 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_ptrinto 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.