如何创建 unique_ptr 并将其添加到方法中的向量?
How can I create and add a unique_ptr to a vector in a method?
我正在尝试使用多态性来表示各种树(解析器的终端节点和非终端节点)。 classes Node
之一包含指向 Base
的子 classes 的智能指针向量。我想使用只接受 Node
引用的方法向该向量添加更多节点,而不必在 class 之外创建智能指针(或者这是糟糕的做法?)。
void addNode(const std::unique_ptr<Node> &&node)
重载有效,但我想使用
void addNode(const Node &&node)
过载。
无论我做什么,我似乎都无法在不破坏复制省略规则或调用 Node 的复制构造函数的情况下创建此智能指针并将其移动到向量中,我不确定为什么。看起来 make_unique
总是在调用 Node.js 的复制构造函数。我试过使用这些语句:
nodes.push_back(std::make_unique<Node>(node));
给出编译器错误 call to implicitly-deleted copy constructor
。这是有道理的,以为我只需要 std::move
它。
nodes.push_back(std::move(std::make_unique<Node>(node)));
同样的错误,还有:moving a temporary object prevents copy elision
.
nodes.push_back(std::make_unique<Node>(std::move(node)));
刚给出call to implicitly-deleted copy constructor
.
nodes.push_back(std::move(std::make_unique<Node>(std::move(node))));
甚至尝试过这个,也给出了两个错误。
这是我的重现:
#include <iostream>
#include <string>
#include <vector>
class Base {};
class Node;
typedef std::vector<std::unique_ptr<Base> > Nodes;
class Node : public Base {
Nodes nodes;
public:
Node() {};
void addNode(const Node &&node) {
nodes.push_back(std::make_unique<Node>(node));
//nodes.push_back(std::move(std::make_unique<Node>(node)));
//nodes.push_back(std::make_unique<Node>(std::move(node)));
//nodes.push_back(std::move(std::make_unique<Node>(std::move(node))));
}
void addNode(std::unique_ptr<Node> &&node) {
nodes.push_back(std::move(node));
}
};
int main()
{
Node rootNode;
rootNode.addNode(Node());
rootNode.addNode(std::make_unique<Node>());
return 0;
}
我正在使用 Clang++ 和 C++20 在 MacOS 上编译。
您想如何移动 const 对象?
应该是:
void addNode(Node &&node) {
nodes.push_back(std::make_unique<Node>(std::move(node)));
}
通过移动,你修改了被移动的实例,所以它应该是可修改的。
错误是由于 void addNode(const Node &&node)
使用了一个 const 右值引用,这是非常可疑的实用程序的一个很大的奇怪之处(有一些极端情况它们可能有意义,请参阅 this answer 了解更多信息).
鉴于您不能从 const Node&&
移动(毕竟它是常量),隐式生成的移动构造函数 (Node(Node&&)
) 无法匹配。
由于从 C++03 继承的旧怪癖 const T&
可以绑定到右值,因此 const T&&
可以衰减到 const T&
。这导致编译器尝试调用Node(const Node&)
,又名复制构造函数,由于 std::vector<std::unique_ptr<Base>>
不可移动而被删除,这也是由于 std::unique_ptr<T>
不可移动。
我正在尝试使用多态性来表示各种树(解析器的终端节点和非终端节点)。 classes Node
之一包含指向 Base
的子 classes 的智能指针向量。我想使用只接受 Node
引用的方法向该向量添加更多节点,而不必在 class 之外创建智能指针(或者这是糟糕的做法?)。
void addNode(const std::unique_ptr<Node> &&node)
重载有效,但我想使用
void addNode(const Node &&node)
过载。
无论我做什么,我似乎都无法在不破坏复制省略规则或调用 Node 的复制构造函数的情况下创建此智能指针并将其移动到向量中,我不确定为什么。看起来 make_unique
总是在调用 Node.js 的复制构造函数。我试过使用这些语句:
nodes.push_back(std::make_unique<Node>(node));
给出编译器错误 call to implicitly-deleted copy constructor
。这是有道理的,以为我只需要 std::move
它。
nodes.push_back(std::move(std::make_unique<Node>(node)));
同样的错误,还有:moving a temporary object prevents copy elision
.
nodes.push_back(std::make_unique<Node>(std::move(node)));
刚给出call to implicitly-deleted copy constructor
.
nodes.push_back(std::move(std::make_unique<Node>(std::move(node))));
甚至尝试过这个,也给出了两个错误。
这是我的重现:
#include <iostream>
#include <string>
#include <vector>
class Base {};
class Node;
typedef std::vector<std::unique_ptr<Base> > Nodes;
class Node : public Base {
Nodes nodes;
public:
Node() {};
void addNode(const Node &&node) {
nodes.push_back(std::make_unique<Node>(node));
//nodes.push_back(std::move(std::make_unique<Node>(node)));
//nodes.push_back(std::make_unique<Node>(std::move(node)));
//nodes.push_back(std::move(std::make_unique<Node>(std::move(node))));
}
void addNode(std::unique_ptr<Node> &&node) {
nodes.push_back(std::move(node));
}
};
int main()
{
Node rootNode;
rootNode.addNode(Node());
rootNode.addNode(std::make_unique<Node>());
return 0;
}
我正在使用 Clang++ 和 C++20 在 MacOS 上编译。
您想如何移动 const 对象?
应该是:
void addNode(Node &&node) {
nodes.push_back(std::make_unique<Node>(std::move(node)));
}
通过移动,你修改了被移动的实例,所以它应该是可修改的。
错误是由于 void addNode(const Node &&node)
使用了一个 const 右值引用,这是非常可疑的实用程序的一个很大的奇怪之处(有一些极端情况它们可能有意义,请参阅 this answer 了解更多信息).
鉴于您不能从 const Node&&
移动(毕竟它是常量),隐式生成的移动构造函数 (Node(Node&&)
) 无法匹配。
由于从 C++03 继承的旧怪癖 const T&
可以绑定到右值,因此 const T&&
可以衰减到 const T&
。这导致编译器尝试调用Node(const Node&)
,又名复制构造函数,由于 std::vector<std::unique_ptr<Base>>
不可移动而被删除,这也是由于 std::unique_ptr<T>
不可移动。