如何处理模板类中的指针?

时间:2014-02-04 09:58:19

标签: c++ pointers

在考虑像BinaryTree这样的模板化数据结构时,处理指针类型的最简洁方法是什么?

如果树保存指针,则在删除子树时必须将它们指向的内存返回到堆中。但是我怎么能从BinaryTree类中分辨出来,它是由malloc还是new分配的?

一种解决方案是设置标志,指​​示存储的数据类型。但是,我的课程将依赖于外部的正确使用...

另一个想法是将某种向量传递给可能删除子树的所有BinaryTree方法。每当删除子树时,它会将存储的数据添加到向量中,最后我可以从BinaryTree外部正确处理它们。

但这听起来像是一个麻烦的解决方案,可能有更好的方法。

5 个答案:

答案 0 :(得分:4)

将原始指针存储在像BinaryTree这样的容器中的唯一原因是,如果要引用在其他地方存储/管理的对象。在这种情况下,只需删除指针(而不是它们指向的对象)就足够了,因为删除对象是在别处处理的。

如果要管理树中动态分配的对象,请使用例如std::unique_pointer<T>作为容器的元素类型。在这种情况下,再次简单地删除存储的元素将会这样做,因为删除std::unique_pointer<T>意味着删除它所指向的对象。

答案 1 :(得分:2)

首先:在C ++中避免使用malloc。然后你不必担心是否用malloc或new分配了一些东西,因为你从来没有用malloc分配任何东西。虽然你的问题即使在那时也没有解决,但因为数组的deletedelete[]之间存在差异......所以你不能真正删除其他人的指针。我想一个好的口头禅是“在我们信任的析构函数中”。 :)

其次:如果您正在尝试创建容器类,那么如果您希望它参与资源管理,请不要提交原始指针。想想当你制作std::vector<std::string *>时会发生什么。当该向量运行其析构函数时,它是否对包含的指针执行任何操作?不。就它而言,它可能也一直保持整数。假设终身管理在其他地方得到处理。 (至少,我们希望......!)

如果您确实希望容器参与生命周期管理,则需要传递包装指针的对象并说出一些协议。虽然您可以自由定义任何您喜欢的协议,但最简单的协议是已经标准化的协议。在C ++中,您的对象是否支持复制构造,移动构造,普通析构函数等等。期待标准库容器的灵感是一个良好的开端。

因此,请考虑您的容器将对象放入destroy排队向量中,然后调用方法来销毁它们。批量销毁对象可能有一个优势,但为什么通用容器会关注这个?为什么包含的对象不能像往常一样运行它们的析构函数,而是让析构函数将包装对象的内容放入由某种“包含的对象管理器”维护的队列中?如果这是您真正需要的,您可以将问题与容器完全分开。通常,你只是不需要它。

正如其他人所提到的,如果你还没有,请调查shared_ptrunique_ptr,你可能会从auto_ptr was decided to be not cool

的案例中了解到一些事情。

答案 2 :(得分:1)

使用c ++ 11中的共享指针(boost::shared_ptrstd::shared_ptr)将数据存储在树中。

答案 3 :(得分:1)

我已经提出了很多好的建议,我只想添加一种强大的(但可能是矫枉过正的)替代技术:如果你看一下标准容器,你会注意到它们不仅仅是元素类型的模板 - 它们也是接受分配器策略。您可以使用相同的技术来提供灵活的资源分配,不仅适用于元素,还适用于容器可能需要的节点或其他数据的内存。遗憾的是,C ++ 03期望分配器不具有状态,因此它们不是很有用,但是如果你正在设计自己的容器,那么你没有理由不允许这样做。如果您对这种技术感兴趣,可能需要阅读Andrei Alexandrescu的Modern C ++ Design。

答案 4 :(得分:0)

这里有几个问题。我正在回答“但我怎么能从BinaryTree类内部告诉它,它是由malloc还是new分配的?”

答案很简单。 不要将C ++ alloc(new / delete)与C alloc(malloc / free)混合使用!。它不会起作用。有关详细信息,请参阅What is the "correct" way to reconcile malloc and new in a mixed C/C++ program?http://www.codeproject.com/Articles/6555/To-new-is-C-To-malloc-is-C-To-mix-them-is-sin