2010-09-25 48 views
8

我最近被介绍到存在auto_ptrshared_ptr,我有一个非常简单/天真的问题。指针vs auto_ptr vs shared_ptr

我试图实现一个数据结构,我需要指向一个Node(其中多于1个)数字可能会改变的孩子。这是最好的选择,为什么:

​​

我不知道,但我想auto_ptr不适用于数组。我不是,也不确定我是否应该使用双指针。谢谢你的帮助。

+0

的auto_ptr已被弃用在C++ 11,应该尽可能避免在代码中老年C++版本,以及。 – Nikko 2015-10-09 12:41:06

+0

'auto_ptr'已被弃用,因为它不必要地难以正确使用。改为使用'unique_ptr',它与'auto_ptr'基本相同,只是它工作正常并且还支持数组。它自C++ 11开始提供。 – nwp 2015-10-09 12:41:49

+0

也看看http://stackoverflow.com/questions/3987521/how-bad-is-to-use-void-pointer-in-stdvector-declaration – fizzbuzz 2016-02-18 12:38:14

回答

7

你说得对,auto_ptr不适用于数组。当它销毁它拥有的对象时,它使用delete object;,所以如果你使用new objects[whatever];,你会得到未定义的行为。也许有点微妙,auto_ptr不符合“可复制”的要求(因为标准定义了术语),因此您不能创建auto_ptr的容器(矢量,双排扣,列表等)。

A shared_ptr也适用于单个对象。这是为了您拥有共享所有权,并且只有当全部业主超出范围时才需要删除对象。除非你没有告诉我们有什么事情,否则很可能会非常不适合你的要求。

您可能想看看另一个对您而言可能是新的课程:提升ptr_vector。至少根据你所说的话,它似乎比auto_ptrshared_ptr更符合你的要求。

+0

谢谢!所以我知道我应该使用'ptr_vector'或'Node * children'。我不能使用'auto_ptr'来指向Node的'std :: vector'吗?此外,是'Node * children'的权利,还是我应该更喜欢'Node ** children'?我有点困惑。抱歉在这里打包太多问题。 – 2010-09-25 21:44:11

+0

@ myle:不知道你在做什么更多,这很难说。基本上,一个'Node *'会给你一个指向任意数量节点的点,所以这些节点基本上是其父节点的一部分,而不仅仅是链接到它。一个'Node **'可以让你有一个指向节点的动态指针数组,但是你必须自己管理这个动态数组。 – 2010-09-25 21:51:35

3

我在相似的情况下成功使用了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); 
    } 

}; 
+0

另外,请注意,您可以将自己的析构函数提供给shared_ptr,以便通过调用delete []来代替普通的delete来管理数组。 – QuesterZen 2015-10-10 04:53:09

+0

为数组添加自定义删除程序的最简单(但稍微难看)的方法是使用lambda函数,该函数作为额外参数传递给构造函数。例如:'std :: shared_ptr sp(new T [n],[](T * p){delete [] p;})''。对于unique_ptrs,为此提供了一个特殊版本:'std :: unique_ptr up(new T [n])',它调用delete []而不是delete。 – QuesterZen 2015-10-11 23:29:55

1

auto_ptr是赞成std::unique_ptr和BTW弃用。 std::unique_ptr对数组起作用。你只需要C++ 11的支持。而且已经有很多关于智能指针的资源,并将语义移到那里。 auto_ptrunique_ptr之间的主要区别在于auto_ptr在调用复制构造函数时禁止移动unique_ptr禁止复制构造函数,但在调用移动构造函数时允许move。因此,您需要使用移动语义进行C++ 11支持。