最近我介绍了auto_ptr
和shared_ptr
的存在,我有一个非常简单/幼稚的问题。
我尝试实现一个数据结构,我需要指向一个Node
的子项,这些子项可以更改(超过1且其数量)。哪个是最好的选择,为什么:
class Node
{
public:
// ...
Node *children;
private:
//...
}
class Node
{
public:
// ...
share_ptr<Node> children;
private:
//...
}
我不确定,但我认为auto_ptr
对数组不起作用。我也不确定是否应该使用双指针。谢谢你的帮助。
答案 0 :(得分:8)
你是对的,auto_ptr不适用于数组。当它破坏它拥有的对象时,它使用delete object;
,所以如果你使用new objects[whatever];
,你将得到未定义的行为。也许更巧妙的是,auto_ptr
不符合“可复制”的要求(因为标准定义了术语),因此您无法创建{{{vector,deque,list等)的容器(vector,deque,list等)。 1}}要么。
auto_ptr
也适用于单个对象。这是针对您拥有共享所有权并且仅在所有所有者超出范围时才需要删除对象的情况。除非你有什么事情没有告诉我们,否则很可能它也不能很好地满足你的要求。
您可能希望查看另一个可能对您不熟悉的课程:提升ptr_vector。至少根据您所说的内容,它似乎比shared_ptr
或auto_ptr
更符合您的要求。
答案 1 :(得分:3)
我在类似的情况下成功使用了std::vector<std::shared_ptr<Node> > children
。
使用shared_ptrs向量而不是数组的主要好处是可以为您处理所有资源管理。这在两种情况下特别方便:
1)当向量不再在范围内时,它会自动调用其所有内容的删除。在这种情况下,子节点的引用计数将减少1,如果没有其他引用它,则将在对象上调用delete。
2)如果您在其他地方引用节点,则不存在悬挂指向已删除对象的指针的风险。只有在没有对象的引用时才会删除该对象。
除非你想要的行为要复杂得多(也许有必要使用数组的原因),我建议这对你来说可能是一个很好的方法。
这个想法的简单实现:
class Node {
private:
T contents;
std::vector<std::shared_ptr<Node> > children;
public:
Node(T value) : contents(value) {};
void add_child(T value) {
auto p = std::make_shared<Node>(value);
children.push_back(p);
}
std::shared_ptr<Node> get_child(size_t index) {
// Returning a shared pointer ensures the node isn't deleted
// while it is still in use.
return children.at(index);
}
void remove_child(size_t index) {
// The whole branch will be destroyed automatically.
// If part of the tree is still needed (eg. for undo), the
// shared pointer will ensure it is not destroyed.
children.erase(children.begin() + index);
}
};
答案 2 :(得分:2)
auto_ptr
已弃用,以支持std::unique_ptr
和btw。 std::unique_ptr
适用于数组。你只需要c ++ 11支持。并且已经有很多关于智能指针和移动语义的资源。 auto_ptr
和unique_ptr
之间的主要区别在于,auto_ptr
在调用复制构造函数时执行移动,而unique_ptr
禁止复制构造函数,但在调用move构造函数时允许move
。因此,你需要c ++ 11支持移动语义。
答案 3 :(得分:1)
Stroustrup讨论了“什么是auto_ptr以及为什么没有auto_array”的问题,并得出结论认为不需要后者,因为可以使用向量完成所需的功能。