类对象的自毁

时间:2017-04-18 23:17:24

标签: c++

我很难释放以这种方式分配的内存

Text * text = new Text();

我有迭代器

 for(iterator = textList.begin() ; iterator != textList.end() ; ++iterator)
{
    if((*iterator)->getTitle() == element.toStdString())
    {
        textList.remove((*iterator));
        break;
    }
}

textList包含指向类对象的指针

    list<Text *>textList;

和析构函数

~Text() {delete this;}

我已经读过remove()方法实际上为对象调用析构函数,但由于某种原因,情况并非如此。 Valgrind清楚地显示了内存泄漏。所以,如果你能给我一个如何释放记忆的暗示,我真的很感激。

4 个答案:

答案 0 :(得分:2)

这当然看起来很可疑:

~Text() {delete this;}

为什么要在删除时调用delete this? 您存储指向文本的指针列表。如果您自己创建Text实例,那么您还需要删除它们(或使用一些智能指针来帮助您这样做),或者,您可以存储Text对象列表:

list<Text> textList;
m_textList.push_back(Text("Some text"));

for (iterator = textList.begin() ; iterator != textList.end() ; ++iterator)
{
    if (iterator->getTitle() == element.toStdString())
    {
        textList.remove(iterator);
        break;
    }
}

答案 1 :(得分:1)

使用std :: unique_ptr,忘掉破坏。

std::vector<std::unique_ptr<Text>> m_text;

std::unique_ptr<Text> text_ptr(new Text());
m_text.push_back(std::move(text_ptr));
//m_text[i]->function();

答案 2 :(得分:0)

您的问题的评论和答案有一些很好的建议。

但我有一种方法可以在scott meyers书中读到有效的STL,完全符合您的情况。

以下代码中的注释给出了足够的解释。

//g++  5.4.0
#include <algorithm>
#include <iostream>
#include <list>


//A SAMPLE TEXT CLASS TO TEST
class Text
{
public:
    Text()
    {
        std::cout<<"constructor"<<std::endl;
    }

    ~Text()
    {

        std::cout<<"destructor"<<std::endl;
    }

    std::string getTitle()
    {
        return "test";
    }
};



//DECLARE A GLOBAL FUNCTION TO DELETE TEXT OBJECT IN CASE YOUR CONDITION IS MET 
void removeText(Text*& txt) 
{   
    if (txt->getTitle() == "test" ) { 
        delete txt; // delete the pointer
        txt = 0;//and set it to null
    }
}


int main()
{
    //CREATE A LIST
    std::list<Text*> textList;


    //CREATE TEXT OBJECTS
    Text *t1 = new Text();
    Text *t2 = new Text();
    Text *t3 = new Text();
    Text *t4 = new Text();

    //PUSH BACK THEM INTO LIST
    textList.push_back(t1);
    textList.push_back(t2);
    textList.push_back(t3);


    //CLEAN YOUR LIST FOR THE REQUIRED CONDITION
    for_each(textList.begin(), textList.end(),removeText);

    //USE ERASE - REMOVE IDIOM TO CLEAN YOUR LIST.
    textList.erase(std::remove(textList.begin(), textList.end(),static_cast<Text*>(0)),
               textList.end());

    std::cout<<textList.size()<<std::endl;

}

以上程序的输出:

constructor
constructor
constructor
constructor
destructor
destructor
destructor
0

答案 3 :(得分:0)

  

我已经读过remove()方法实际上为对象调用了析构函数,但由于某种原因,情况并非如此。

因为您在列表中存储指针,而不是对象。并且容器肯定不会尝试为您调用删除。为什么?因为它无法知道对象是否是由new创建的。这完全合法:

list<Text*> textList;

Text text;

textList.push_back(&text);
// You can safely use textList as long as text is in scope.
...

在析构函数中删除this是完全错误的。如果对象在堆栈中,则不需要将其删除。如果对象是由new创建的,就像@Pavel所说的那样,代码中的某个地方指针已被删除。无论哪种方式,您的程序都会崩溃。

在编写现代C ++代码时,应避免使用newdelete。赫伯·萨特(Herb Sutter)看这个talk。总结一下: Leak Freedom in C++