63

考虑这段代码:

#include <vector>

void Example()
{
    std::vector<TCHAR*> list;
    TCHAR* pLine = new TCHAR[20];
    list.push_back(pLine);
    list.clear();    // is delete called here?
    // is delete pLine; necessary?
}

是否list.clear()调用delete每个元素?即我必须在之前/之后释放内存list.clear()吗?

4

6 回答 6

53

std::vector调用时确实调用了它包含的每个元素的析构函数clear()。在您的特定情况下,它会破坏指针但对象仍然存在。

智能指针是正确的方法,但要小心。auto_ptr不能在 std 容器中使用。boost::scoped_ptr也不能。boost::shared_ptr可以,但它不适用于您的情况,因为您没有指向对象的指针,您实际上正在使用数组。因此,您的问题的解决方案是使用boost::shared_array.

但我建议您std::basic_string<TCHAR>改用,这样您就不必处理内存管理,同时仍然可以获得使用字符串的好处。

于 2009-02-27T09:35:39.927 回答
40

否(您需要按照您在示例中的建议在最后自己进行删除,因为秃头指针的破坏不会做任何事情)。但是您可以使用 boost [或其他基于 RAII 的惯用语] 智能指针使其做正确的事情(auto_ptr在容器中无法正常工作,因为它在复制等下具有不兼容的行为),但请确保您了解陷阱这样的智能指针在使用前。(正如 Benoit 所提到的,在这种情况下,这basic_string就是您真正要在这里寻找的东西。)

话虽如此,需要了解智能指针的缺陷,让它们隐式地处理内存管理,这样您就不必显式地进行操作,这样不容易出错。

编辑:由于 Earwicker 和 James Matta 的大力推动,对 Benoit 进行了大幅修改,以包含 Benoit 带来的更为彻底的答案 - 感谢您推动我对此进行尽职调查!

于 2009-02-27T09:28:29.897 回答
9

这是您可以判断它没有的一种方法 - 在未完全定义的类上尝试它:

#include <vector>
class NotDefined;

void clearVector( std::vector<NotDefined*>& clearme )
{
    clearme.clear();    // is delete called here?
}

如果此代码段编译,则它不能调用析构函数,因为未定义析构函数。

于 2009-02-27T13:32:18.720 回答
8

您可以编写一个简单的模板函数来为您执行此操作:

template <class T>
void deleteInVector(vector<T*>* deleteme) {
    while(!deleteme->empty()) {
        delete deleteme->back();
        deleteme->pop_back();
    }

    delete deleteme;
}

也许这里的某些东西是不好的做法,但我不这么认为。尽管评论总是很好,但对我来说看起来还不错。

于 2009-11-16T04:47:33.760 回答
6

没有。它不会这样做,因为不能保证您不会在其他任何地方使用指针。如果它不是指针变量,它将释放它们(通过调用析构函数)

于 2009-02-27T09:29:13.953 回答
0

您也许还可以使用Boost Pointer Container Library。这里没有特别推荐(再次因为您使用数组而不是单个对象,尽管std::string会处理这一点),但它是一个有用且鲜为人知的库,可以解决标题中所述的问题。

于 2009-02-27T18:56:52.607 回答