I'm trying to create a unique pointer to a <Node> type variable:
#include <memory>
struct Node
{
int val;
std::unique_ptr<Node> next;
Node(int value, std::unique_ptr<Node> nextNode) : val(value), next(std::move(nextNode)){};
}
int main()
{
Node headNode = Node(1, nullptr);
std::unique_ptr<Node> head = std::make_unique<Node>(headNode);
return 0;
}
And when I'm compiling this code I'm getting the following error:
error: call to implicitly-deleted copy constructor of 'Node'
return unique_ptr<_Tp>(new _Tp(_VSTD::forward<_Args>(__args)...));
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: in instantiation of function template specialization 'std::make_unique<Node, Node &>' requested here
std::unique_ptr<Node> head = std::make_unique<Node>(headNode);
^
note: copy constructor of 'Node' is implicitly deleted because field 'next' has a deleted copy constructor
std::unique_ptr<Node> next;
^
note: copy constructor is implicitly deleted because 'unique_ptr<Node>' has a user-declared move constructor
unique_ptr(unique_ptr&& __u) _NOEXCEPT
CodePudding user response:
std::make_unique<Node>(headNode);
This constructs a unique Node by attempting to copy-construct it from another Node.
std::unique_ptr is not copyable, by definition (that would be due to the "unique" part of "unique_ptr"). This means that any class that contains a std::unique_ptr is not copyable by default, and its default copy-constructor is deleted.
This is the reason for your compilation error. You would get the same compilation error without involving std::unique_ptr:
Node node2{headNode};
This results in the same compilation error. You have two options:
Implement a copy constructor for
Nodethat does whatever would be a meaningful result for copy-constructing yourNode.Re-engineer your code, in some way, that avoids copy-constructing
Nodes.
If your described goal is "a unique pointer to a type variable", then this does not require copy-constructing it, merely:
std::unique_ptr<Node> head = std::make_unique<Node>(1, nullptr);
CodePudding user response:
Should work
#include <memory>
struct Node
{
using NodePtr = std::unique_ptr<Node>;
int val;
NodePtr next;
Node(int value, NodePtr&& nextNode)
: val(value)
, next(std::move(nextNode))
{
}
};
int main()
{
auto headNode = std::make_unique<Node>(1, nullptr);
auto head = std::make_unique<Node>(0, std::move(headNode));
return 0;
}
At line std::unique_ptr<Node> head = std::make_unique<Node>(headNode);
make_unique calls ctor for Node and unique_ptr (making 1 allocation)
So, args passed into std::make_unique() are used to build T instance.
Your Node has ctor, that takes 2 params, not 1.
std::unqiue_ptr hasn't copy ctor and copy operator=() (e.g auto newPtr = oldPtr), so every function that deals with std::unique_ptr in argument list, should take this smart pointer by rvalue-reference - std::unique_ptr<T>&&. And final call must look like this f(std::move(ptr)), where f - function, or in our case - ctor of Node
If you are not familiar with T - consider T as AnyType
