Why can I not push_back a unique_ptr into a vector?
You need to move the unique_ptr
:
vec.push_back(std::move(ptr2x));
unique_ptr
guarantees that a single unique_ptr
container has ownership of the held pointer. This means that you can't make copies of a unique_ptr
(because then two unique_ptr
s would have ownership), so you can only move it.
Note, however, that your current use of unique_ptr
is incorrect. You cannot use it to manage a pointer to a local variable. The lifetime of a local variable is managed automatically: local variables are destroyed when the block ends (e.g., when the function returns, in this case). You need to dynamically allocate the object:
std::unique_ptr<int> ptr(new int(1));
In C++14 we have an even better way to do so:
make_unique<int>(5);
What is the correct usage of std::unique_ptr while pushing into std::vector
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()
.
error with vector, unique_ptr, and push_back
push_back
expects an std::unique_ptr
, when passing raw pointer like new Square
, which is considered as copy-initialization, the raw pointer needs to be converted to std::unique_ptr
implicitly. The implicit conversion fails because std::unique_ptr
's conversion constructor from raw pointer is marked as explicit
.
emplace_back
works because it forwards arguments to the constructor of std::unique_ptr
and construct element in direct-initialization form, which considers explicit
conversion constructors.
The arguments args... are forwarded to the constructor as
std::forward<Args>(args)...
.
Why does push_back fail for unique_ptr of string vectors?
You have declared a std::unique_ptr
using its default constructor, so it is holding a nullptr
pointer. You are not creating a std::vector
object for it to point at.
Use new
to create the std::vector
:
int main() {
auto vect = std::unique<std::vector<std::string>>(new std::vector<std::string>);
// or:
// std::unique<std::vector<std::string>> vect(new std::vector<std::string>);
vect->push_back("abc");
vect->emplace_back("abc");
return 0;
}
Or, in C++14 and later, use std::make_unique()
instead of constructing the std::vector
manually:
int main() {
auto vect = std::make_unique<std::vector<std::string>>();
vect->push_back("abc");
vect->emplace_back("abc");
return 0;
}
However you really should not create standard containers in dynamic memory, unless you absolutely need to.
int main() {
std::vector<std::string>> vect;
vect.push_back("abc");
vect.emplace_back("abc");
return 0;
}
How to push_back a unique_ptrBase& to vectorunique_ptrDerived
You can iterate on fromBase
list and make your checks, if that requirement is met then you can simply release
the pointer - which gives away the base pointer without calling destructor on it. Just make sure to remove such empty pointers that were released, in case you need to use fromBase
vector again.
WANDBOX LINK
#include <iostream>
#include <vector>
#include <memory>
#include <algorithm>
using namespace std;
class Base{ public: virtual ~Base() = default; };
class Derived: public Base {};
int main() {
vector<unique_ptr<Base>> fromBase;
vector<unique_ptr<Derived>> toDerived;
fromBase.emplace_back(make_unique<Base>());
fromBase.emplace_back(make_unique<Base>());
fromBase.emplace_back(make_unique<Derived>());
for(auto& p: fromBase) {
Derived* d = dynamic_cast<Derived *>(p.get());
// make other checks here
if(d != nullptr) {
toDerived.emplace_back(d);
p.release();
}
}
// make sure to remove released pointers
fromBase.erase(remove_if(fromBase.begin(), fromBase.end(), [](const auto& p) { return !p; }), fromBase.end());
cout << fromBase.size() << " " << toDerived.size() << endl;
}
Pushing an object with unique_ptr into vector in C++
State
is not copyable, but only moveable; But for states.push_back(nstate);
, nstate
is an lvalue (as a named variable), which can't be moved from. Then a copy is tried to perform but it's not allowed.
To solve it you could use std::move
(to turn it to an rvalue):
states.push_back(std::move(nstate));
LIVE
Note that after the move operation, the data member of nstate
(including the vector and its content) will be moved too.
Can't push_back an unique_ptr in a vector
When using unique_ptr
you need to explicitly define the class T
where-ever you declare the unique_ptr<T>
. I.e. include the header for the class GameState
, do not forward declare in the header game.h
.
This will get rid of error: invalid application of 'sizeof' to incomplete type 'GameState'
.
You can find more detailed answer here.
Related Topics
How to Redirect Cin and Cout to Files
Is Std::Unique_Ptr≪T≫ Required to Know the Full Definition of T
How to "Return an Object" in C++
Difference Between _Tmain() and Main() in C++
Capturing Function Exit Time With _Gnu_Mcount_Nc
Can You Use 2 or More or Conditions in an If Statement
How to Create a Generic Object Model For Use in Qml
What Is the Point of Function Pointers
C++11 Return Value Optimization or Move
Finding C++ Static Initialization Order Problems
Make_Unique and Perfect Forwarding
Why Is the Type of the Main Function in C and C++ Left to the User to Define
When I Change a Parameter Inside a Function, Does It Change For the Caller, Too
Are the Days of Passing Const Std::String & as a Parameter Over