【问题标题】:stl vector memory managementstl 向量内存管理
【发布时间】:2009-06-17 19:40:55
【问题描述】:

我使用的是 borland 2006 c++,并且有以下代码。我正在使用向量,但无法理解为什么不调用析构函数。

基本上我有一个A类

class A
{
private:
    TObjectList* list;
    int myid;
public:
 __fastcall A(int);
 __fastcall ~A();
};

__fastcall A::A(int num)
{
    myid = num;
    list = new TObjectList();

}

__fastcall A::~A()
{
    delete list;
}

int main(int argc, char* argv[])
{
    myfunc();
    return 0;
}

void myfunc()
{
    vector<A*> vec;
    vec.push_back(new A(1));
    vec.push_back(new A(2));
}

根据我的阅读,当变量 vec 超出 myfunc() 的范围时,它应该破坏其包含的元素,因此应该调用 A 的析构函数。我在 ~A() 有一个断点,但从未被调用,我尝试过 resize(),也有擦除方法

TIA

【问题讨论】:

    标签: c++


    【解决方案1】:

    vec 在超出范围时会破坏其元素。这里的问题是 vec 的元素是指向 A 对象的 指针,而不是 A 对象本身。如果你这样做了

    vector<A> vec;
    vec.push_back(A(1));
    vec.push_back(A(2));
    

    ...那么一切都会如你所愿。

    ETA:但请注意,如果您这样做,则必须为 A 定义一个复制构造函数。这应该涉及对 TObjectList 成员进行深层复制。否则,当你复制一个 A 对象时,你会得到两个都指向同一个 TObjectList 的对象,而当第二个对象被销毁时,你的程序就会崩溃。

    【讨论】:

    • 作为旁注。在容器内使用指针时,请勿尝试使用 auto_ptr 进行销毁。 Auto_ptrs 不能在 STL 容器中使用,因为它们是被复制的。
    • 对,但是 boost::shared_ptr AKA std::tr1::shared_ptr 在容器类中工作得很好。
    • 感谢您的解释,另一个快速问题是当我向向量添加一个元素时,析构函数被调用两次,当 vec 超出范围时,我希望它在元素被调用时调用一次复制并添加..
    • 不,它应该被调用两次。发生的情况是您正在创建一个临时的匿名 A 对象并将其传递给 vector 的 push_back 方法。然后,Vector 制作该临时 A 对象的副本以在内部存储。从 push_back 返回后,临时 A 对象立即超出范围并被破坏。然后,当向量本身超出范围并破坏时,它会破坏它所拥有的复制的 A 对象。这就是为什么您需要 A 的复制构造函数来执行正确的深层复制。
    【解决方案2】:

    A 的析构函数未被调用,因为您没有A 的向量。您有一个指向A 的指针向量,并且调用了指针的析构函数。指针没有析构函数,所以什么也不会发生。

    删除所有内容的一种方法是手动执行类似的操作

    while (!vec.empty())
    {
        delete vec.back();
        vec.pop_back();
    }
    

    【讨论】:

      【解决方案3】:

      已经有很多好的答案了,但我会再补充一个:

      使用来自Boost Pointer Container Libraryboost::ptr_vector,而不是 std::vector。当向量超出范围时,它将删除对象,从而调用析构函数。

      【讨论】:

        【解决方案4】:

        获取 Boost 库,在上面任何有原始指针的地方都可以使用 boost::shared_ptr 代替。 (嗯,不在 main() 的签名中。)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-06-08
          • 1970-01-01
          • 2010-12-28
          • 2010-11-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-05
          • 2011-01-19
          相关资源
          最近更新 更多