【问题标题】:Destructor never call析构函数从不调用
【发布时间】:2015-03-29 00:15:32
【问题描述】:

我不明白为什么 ListELement 的析构函数永远不会被调用。
我使用类 Base 作为计数器,ListELement 派生自 Base 以使用计数器。

节目:

#include <iostream>
#include <random>
#include <functional>

using namespace std;

class Base{
    protected:
    static int count;
};


template <class T>
class ListElement: public Base{

    public:
    ListElement(const T& value): next(NULL), data(value) { count++;}
    ~ListElement() { cout<<"dead:"<<count<<endl;}

    //Setter
    void SetData(const T& value) { data=value; }
    void SetNext(ListElement* elem) { next = elem; }
    //Getter
    const T& GetData() const { return data; }
    ListElement* GetNext() const { return next; } 

    private:
    T data; 
    ListElement* next;
};

int Base::count = 0;

int main(){
    random_device rd;
    default_random_engine generator(rd());
    uniform_int_distribution<int> distribution(1,100);
    auto dice = bind(distribution, generator);

    int nListSize = 1;
    ListElement<int>* nMyList = new ListElement<int>(999);

    ListElement<int>* temp = nMyList;//nMyList is the first element
    for(int i=0; i<10; ++i) {
        ListElement<int>* k = new ListElement<int>(dice()); //New element
        temp->SetNext(k);
        temp = temp->GetNext(); 
        nListSize++;    
    }

    temp=nMyList;
    for(int i=0; i<nListSize; ++i){
        cout<<"Value["<<i<<"]: "<<temp->GetData()<<endl;
        temp = temp->GetNext();
    }

    return 0;
}

这是我的输出:

Value[0]: 999
Value[1]: 61
Value[2]: 14
Value[3]: 96
Value[4]: 51
Value[5]: 15
Value[6]: 37
Value[7]: 83
Value[8]: 1
Value[9]: 42
Value[10]: 95

如果我输入echo &amp;?,控制台会返回我的0,所以一切都会好起来的。

【问题讨论】:

  • 如果你用new创建一个对象,你必须用delete手动销毁它。
  • 好的!但是当程序退出时,它应该会破坏一切,对吧?
  • 您也应该在遇到此类问题时使用-Wall-Werror 运行编译。
  • 当程序存在时,它会将内存释放回系统,它不会到处调用随机析构函数:)。

标签: c++ c++11


【解决方案1】:

new 几个ListElement&lt;int&gt; 但从来没有delete 他们。

对于具有自动存储持续时间的变量,会自动调用析构函数。它们不适用于您手动为其分配内存的变量。

如果您添加正确的删除语句,您将运行 dtor。

注意:如果您绝对需要指针,您应该查看std::shared_ptr/std::unique_ptr,因为您将拥有指针的语义,并为您完成内存管理,即指针将被正确删除一次它没有被任何地方引用。

【讨论】:

    【解决方案2】:

    对于每个显式的new 调用,您将需要一个显式的delete 调用,除非您的ListElement 析构函数有一个循环来删除这些节点。

    【讨论】:

      【解决方案3】:

      因为使用 operator new 创建的对象必须使用 operator delete 显式释放。

      这可以通过使用工具来实现,或者将 nMyList 的类型更改为(在 C++-11 之前)

      std::auto_ptr<ListElement<int> > nMyList(new ListElement<int>(999));
      

      或(来自 C++11,弃用了 auto_ptr)

      std::unique_ptr<ListElement<int> > nMyList(new ListElement<int>(999));
      

      如果你坚持不改变nMyList的类型,那么

      delete nMyList;
      

      在 main() 的末尾也可以工作(智能指针类型的优点是它们破坏了它们管理的对象)。

      【讨论】:

        猜你喜欢
        • 2015-02-21
        • 2013-01-01
        • 1970-01-01
        • 2017-02-08
        • 2011-04-16
        • 2015-12-20
        • 2019-01-09
        • 2023-03-31
        • 2015-10-07
        相关资源
        最近更新 更多