我最近被介绍到存在auto_ptr
和shared_ptr
,我有一个非常简单/天真的问题。指针vs auto_ptr vs shared_ptr
我试图实现一个数据结构,我需要指向一个Node
(其中多于1个)数字可能会改变的孩子。这是最好的选择,为什么:
我不知道,但我想auto_ptr
不适用于数组。我不是,也不确定我是否应该使用双指针。谢谢你的帮助。
我最近被介绍到存在auto_ptr
和shared_ptr
,我有一个非常简单/天真的问题。指针vs auto_ptr vs shared_ptr
我试图实现一个数据结构,我需要指向一个Node
(其中多于1个)数字可能会改变的孩子。这是最好的选择,为什么:
我不知道,但我想auto_ptr
不适用于数组。我不是,也不确定我是否应该使用双指针。谢谢你的帮助。
你说得对,auto_ptr不适用于数组。当它销毁它拥有的对象时,它使用delete object;
,所以如果你使用new objects[whatever];
,你会得到未定义的行为。也许有点微妙,auto_ptr
不符合“可复制”的要求(因为标准定义了术语),因此您不能创建auto_ptr
的容器(矢量,双排扣,列表等)。
A shared_ptr
也适用于单个对象。这是为了您拥有共享所有权,并且只有当全部业主超出范围时才需要删除对象。除非你没有告诉我们有什么事情,否则很可能会非常不适合你的要求。
您可能想看看另一个对您而言可能是新的课程:提升ptr_vector。至少根据你所说的话,它似乎比auto_ptr
或shared_ptr
更符合你的要求。
谢谢!所以我知道我应该使用'ptr_vector'或'Node * children'。我不能使用'auto_ptr'来指向Node的'std :: vector'吗?此外,是'Node * children'的权利,还是我应该更喜欢'Node ** children'?我有点困惑。抱歉在这里打包太多问题。 – 2010-09-25 21:44:11
@ myle:不知道你在做什么更多,这很难说。基本上,一个'Node *'会给你一个指向任意数量节点的点,所以这些节点基本上是其父节点的一部分,而不仅仅是链接到它。一个'Node **'可以让你有一个指向节点的动态指针数组,但是你必须自己管理这个动态数组。 – 2010-09-25 21:51:35
我在相似的情况下成功使用了std::vector<std::shared_ptr<Node> > children
。
使用shared_ptrs而不是数组的向量的主要好处是所有的资源管理都是为您处理的。这在以下两种情况下非常方便:
1)当矢量不在范围内时,它会自动调用删除其所有内容。在这种情况下,子节点的引用计数将减1,如果没有别的引用计数,则将在该对象上调用删除。
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);
}
};
另外,请注意,您可以将自己的析构函数提供给shared_ptr,以便通过调用delete []来代替普通的delete来管理数组。 – QuesterZen 2015-10-10 04:53:09
为数组添加自定义删除程序的最简单(但稍微难看)的方法是使用lambda函数,该函数作为额外参数传递给构造函数。例如:'std :: shared_ptr
auto_ptr
是赞成std::unique_ptr
和BTW弃用。 std::unique_ptr
对数组起作用。你只需要C++ 11的支持。而且已经有很多关于智能指针的资源,并将语义移到那里。 auto_ptr
和unique_ptr
之间的主要区别在于auto_ptr
在调用复制构造函数时禁止移动而unique_ptr
禁止复制构造函数,但在调用移动构造函数时允许move
。因此,您需要使用移动语义进行C++ 11支持。
Stroustrup讨论了“什么是auto_ptr以及为什么不存在auto_array”的问题,并得出结论认为不需要后者,因为所需的功能可以通过向量完成。
的auto_ptr已被弃用在C++ 11,应该尽可能避免在代码中老年C++版本,以及。 – Nikko 2015-10-09 12:41:06
'auto_ptr'已被弃用,因为它不必要地难以正确使用。改为使用'unique_ptr',它与'auto_ptr'基本相同,只是它工作正常并且还支持数组。它自C++ 11开始提供。 – nwp 2015-10-09 12:41:49
也看看http://stackoverflow.com/questions/3987521/how-bad-is-to-use-void-pointer-in-stdvector-declaration – fizzbuzz 2016-02-18 12:38:14