4

我有一张将整数与(对象的)向量相关联的地图。这些向量代表一组要执行的任务。为了减少使用此地图和矢量时的复制量,我将它们设置为使用指针。

std::map<int, std::vector<MyObject *> *> myMap;

在初始化包含 myMap 的类期间,我通过创建一个填充了新 MyObject 的新向量来填充 myMap。

然而,我关心的是内存管理。现在我把这些不同的对象放在堆的某个地方,当我用完它们时我负责清理它们。我也知道在程序完成之前我永远不会完成它们。但是在 10 周内,当有人决定修改此应用程序的一种巧妙方法是从地图/矢量中删除项目时,该怎么办。这将导致内存泄漏。

我的问题是如何处理这些对象的正确释放,以便即使它们通过 STL 函数被删除,对象也能成功释放?

非常感谢您的帮助,如果我错过了任何重要的信息,请告诉我!谢谢!

4

6 回答 6

8

使用智能指针 boost:shared_ptr 而不是原始指针,这样当对象被销毁时,它也会清除堆分配的内存。

boost::shared_ptr http://www.boost.org/doc/libs/1_39_0/libs/smart_ptr/shared_ptr.htm

还有真的有理由指向向量吗?它们几乎不占用空间,并且 std::map 中的对象无论如何都不会移动(与每次向量重新分配时移动/复制的向量中的对象不同,例如以获得更多空间)。

编辑:shared_ptr 也是 tr1 的一个组件,我很确定它在下一个标准中,所以你的编译器可能已经有了它。还有很多其他的 STL 安全的智能指针可以让您了解如何编写自己的,在 Google 上快速搜索应该可以找到它们。

EDIT2:刚刚检查,TR1 的 Visual Studio 2008 实现包括包含在Visual C++ 2008 Feature Pack中的 shared_ptr 。我希望许多其他供应商至少有部分 TR1 的实现可用,所以如果您不使用 VS,请搜索您的供应商网站以获得 TR1 支持。

于 2009-07-20T11:42:47.803 回答
5

我同意使用智能指针是一个好方法,但至少有两种选择:

a) 复制可能没有您想象的那么昂贵。尝试实现值映射

std::map<int, std::vector<MyObject>> myMap;

b) 将向量替换为您自己的包含向量的类。在那个类析构函数中,处理释放。您还可以提供添加和删除 MyObjects 的方法。

于 2009-07-20T12:00:48.797 回答
1

谢谢大家的好答案。我认为目前我倾向于价值向量解决方案。主要原因是 std::auto_ptr 不适用于集合,因为它是不可复制的。这将是智能指针的唯一实现,我可以使用它而无需经过繁重的审查过程或自己滚动。

好消息是你的回答让我走上了一条非常好的道路。我了解了 RAII、异常处理的危险以及如何将它们最小化,并在我的设计中投入了足够的警惕,以至于我可以对它的“正确性”感到满意。

附上一些我在此过程中发现有用的链接。我希望任何遇到类似问题的人都会发现这些链接很有帮助。


C++ 中的RAII 资源智能指针
Boost 智能指针有关智能指针的
更多背景/实现细节

于 2009-07-22T11:43:16.733 回答
1

使用共享指针(如其他人所建议的那样)是最好的解决方案。

如果你真的知道你永远不会完成它们,那么它们在技术上不需要解除分配。如果这确实是所需的行为,只需记录下来,以免有人在 10 周内出现并将其误认为是真正的泄漏。

于 2009-07-20T11:48:51.270 回答
0

详细说明使用时最小化复制map<,vector<Object>>

仔细看 和 的map接口vector。它们主要返回对包含项目的引用,如果您在传递这些东西时保留引用,则不会发生复制。

不好的例子:

std::vector<MyObject> find_objects( const std::map<int,std::vector<MyObject>> & map, int i ) {
    const std::map<int,std::vector<MyObject>>::const_iterator it = map.find( i );
    if ( it != map.end() )
        return it->second;
    else
        return std::vector<MyObject>();
}
// ...
const std::vector<MyObject> objects = find_objects(/*...*/);

更好的:

const std::vector<MyObject> & find_objects( const std::map<int,std::vector<MyObject>> & map, int i ) {
    const std::map<int,std::vector<MyObject>>::const_iterator it = map.find( i );
    if ( it != map.end() )
        return it->second;
    static const std::vector<MyObject> none();
    return none;
}
// ...
const std::vector<MyObject> & objects = find_objects(/*...*/);

-> 不复制

于 2009-07-22T17:34:34.433 回答
0

如果向量/映射中的不同条目之间没有共享每个指针的所有权,那么您只意味着减少在插入时完成的复制,那么您还应该考虑 boost 的指针容器库。

于 2009-07-20T22:40:44.973 回答