I want to have a vector of pointers to objects in my class. To avoid making a destructor for it I wanted to use std::unique_ptr
, as the objects are created/owned/destructed in my class, but I have a compiler error I can't understand. Next code will serve as a short sample for my problem:
std::unique_ptr<int> createPtr(int value)
{
std::unique_ptr<int> ptr(new int(value));
return ptr;
};
int main()
{
std::vector<std::unique_ptr<int>> vec;
vec.push_back(createPtr(1));
std::unique_ptr<int> ptr = createPtr(2);
vec.push_back(ptr);//error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
}
Can you please explain me why I get this error and what is the correct usage for std::unique_ptr
?
std::unique_ptr is a smart pointer that owns and manages another object through a pointer and disposes of that object when the unique_ptr goes out of scope. The object is disposed of, using the associated deleter when either of the following happens: the managing unique_ptr object is destroyed.
A unique_ptr does not share its pointer. It cannot be copied to another unique_ptr , passed by value to a function, or used in any C++ Standard Library algorithm that requires copies to be made. A unique_ptr can only be moved.
unique_ptr. An unique_ptr has exclusive ownership of the object it points to and will destroy the object when the pointer goes out of scope.
Yes. Well the unique ptr has a function object that by default invokes delete on the pointed to object, which calls the destructor. You can change the type of that default deleter to do almost anything.
Consider the vec.push_back()
. It has two overloads which take either const std::unique_ptr<int>&
or std::unique_ptr<int>&&
. The first overload can never be used. This is because the vector<>
requires the type to be assignable, or movable (C++11 addition). 'Assignability' implies copying. push_back(const T&)
will try to copy (assign) the incoming value to the new space at the end of the container. std::unique_ptr<>
represents a resource that is owned by a single owner. By copying it (the pointer) multiple owners would be present. Because of that unique_ptr
is not copyable.
Having said all of it, you can only use the T&&
overload.
createPtr()
returns std::unique_ptr<int>
, but as this is a temporary result (function return value) it is considered a rvalue reference (implicitly). That is why this can be used.
ptr
is just a std::unique_ptr<int>
which is a lvalue reference (no matter if you put && next to it, as named rvalues are still treated as lvalues). Lvalue is never implicitly converted to rvalue (completely unsafe). But you can basically tell the compiler "Ok, you can take the object I pass you, and I promise I won't expect the argument to be left intact" by using std::move()
.
Either:
vec.push_back(std::move(ptr));
Or:
vec.emplace_back(createPtr(2));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With