如何处理模板类中的指针

How to deal with pointers in template classes?

本文关键字:指针 何处理 处理      更新时间:2023-10-16

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

如果树包含指针,则在删除子树时,指针指向的内存必须返回到堆。但是,我如何从BinaryTree类内部判断它是由malloc还是new分配的?

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

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

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

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

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

首先:在C++中避免malloc。然后你就不必担心某个东西是用malloc分配的还是新的,因为你从来没有用mallock分配过任何东西。尽管您的问题即使在那时也没有得到解决,因为阵列的deletedelete[]之间存在差异。。。所以你不能真的去删除别人给他们的指针。我想一个好的咒语是"在我们信任的析构函数中">。:)

第二:如果你试图创建一个容器类,如果你想让它参与资源管理,就不要给它原始指针。想想当你制作std::vector<std::string *>时会发生什么。当该向量运行其析构函数时,它会对所包含的指针执行任何操作吗?没有。就它而言,它可能一直持有整数。假设终身管理由其他地方负责(至少,我们希望…!)

如果您确实希望您的容器参与终身管理,那么您需要将封装指针并使用某种协议的对象传递给它。虽然你可以自由定义任何你喜欢的协议,但最容易使用的协议是那些已经标准化的协议。在C++中,比如对象是否支持复制构造、移动构造、普通析构函数。。。等等。从标准的图书馆容器中寻找灵感是一个良好的开端。

因此,考虑一下您的容器将对象放在销毁队列向量中,然后调用一个方法来销毁它们的想法。批量销毁对象可能有好处,但为什么通用容器会关心这一点呢?为什么包含的对象不能正常运行其析构函数,而是让析构函数将包装对象的内容放入由某种"包含对象管理器"维护的队列中?如果这是您真正需要的,那么您可以将关注点与容器完全分离。通常情况下,你只是不需要它。

正如其他人所提到的,如果你还没有研究过shared_ptrunique_ptr,你可能会从为什么auto_ptr被认为不是很酷的的案例中学到一些东西

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

已经有很多好的建议了,我只想添加一个强大的(但可能有些过头了)替代技术:如果你查看标准容器,你会注意到它们不仅是在元素类型上模板化的,它们还接受Allocator策略。您可以使用相同的技术来提供灵活的资源分配,不仅针对元素,还针对容器可能需要的节点或其他数据的内存。遗憾的是,C++03期望分配器没有状态,所以它们不是很有用,但如果您正在设计自己的容器,就没有理由不允许这样做。如果你对这类技术感兴趣,你可能想读一下安德烈·亚历山德雷斯库的《现代C++设计》。

这里有几个问题。我在回答"但是我如何从BinaryTree类内部判断它是由malloc分配的还是新的?">

答案很简单不要将C++alloc(new/delete)与C alloc(malloc/free)混合使用。这行不通。看看什么是";正确的";如何在混合C/C++程序中协调malloc和new?或http://www.codeproject.com/Articles/6555/To-new-is-C-To-malloc-is-C-To-mix-them-is-sin了解更多详细信息。