remove_if之后的可用内存

时间:2011-01-13 23:33:32

标签: c++ stl

在下面的示例中,我从列表中删除了pr2的应用程序返回true的范围内的一些元素。

m_list.remove_if(pr2(*tmp_list));

在我看来,有必要删除上面删除的这些对象,因为当我创建它时,我使用" new" (新的CRectangle())。我怎么能这样做?我不知道remove_if之后会删除哪些(以及多少)元素。

// test_cconnection.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <conio.h>
#include <iostream>
#include <list>
#include <algorithm>

using namespace std;

class CDrawObject
{
public:
    virtual ~CDrawObject()
    {
        cout << "Drop CDrawObject: " << id_ << endl;
    }
    int getId() const
    {
        return id_;
    }
    virtual void draw()
    {
    }
protected:
    static int id;
    int id_;
};

class CRectangle : public CDrawObject
{
public:
    CRectangle()
    {
        id_ = id++;
    }
    ~CRectangle()
    {
        cout << "Drop CRectangle: " << id_ << endl;
    }
    virtual void draw()
    {
        cout << "CRectangle, id: " << id_ << endl;
    }
};

class CMarker : public CDrawObject
{
    CDrawObject* obj;
public:
    CMarker(CDrawObject* obj_)
    {
        obj = obj_;     
    }
    ~CMarker()
    {
        cout << "Delete marker of object with id: " << obj->getId() << endl;
    }
    CDrawObject* getObject() const
    {
        return obj;
    }
    virtual void draw()
    {
        cout << "CMarker of oject with id: " << obj->getId() << endl;
    }
};

int CDrawObject::id = 0;

// predicate for compare objects with int id
class pr : public std::unary_function<CDrawObject*, bool>
{
private:
    int id_; 
public: 
    pr(int id): id_(id) {}  
    bool operator()(CDrawObject* arg) const 
    { 
        return (arg->getId() == id_); 
    } 
};

// predicate for check objects with type CMarker and
// compare with CDrawObject* obj
class pr2 : public std::unary_function<CDrawObject*, bool>
{
private:
    CDrawObject* obj_; 
public: 
    pr2(CDrawObject* obj)
    {
        obj_ = obj;
    } 
    bool operator()(CDrawObject* arg) const 
    { 
        if (dynamic_cast<CMarker*>(arg))
            return ((dynamic_cast<CMarker*>(arg))->getObject() == obj_); 
    } 
};

int _tmain(int argc, _TCHAR* argv[])
{
    list<CDrawObject*> m_list;
    list<CDrawObject*>::iterator i_list, tmp_list;

    m_list.push_back(new CRectangle());
    tmp_list = m_list.end();
    m_list.push_back(new CMarker(*--tmp_list));
    m_list.push_back(new CMarker(*tmp_list));

    m_list.push_back(new CRectangle());
    tmp_list = m_list.end();
    m_list.push_back(new CMarker(*--tmp_list));

    m_list.push_back(new CRectangle());
    tmp_list = m_list.end();
    m_list.push_back(new CMarker(*--tmp_list));
    m_list.push_back(new CMarker(*tmp_list));

    // print on screen items of m_list
    for (i_list = m_list.begin(); i_list != m_list.end(); ++i_list)
        (*i_list)->draw();

    // get an iterator to the first element in the range with id_ = 2
    tmp_list = find_if(m_list.begin(), m_list.end(), pr(2));

    if (tmp_list !=  m_list.end())
    {
        // remove from list all elements with type CMarker 
        // and CDrawObject = tmp_list       
        m_list.remove_if(pr2(*tmp_list));
    }

    cout << endl << "--------" << endl;

    // print on screen items of m_list
    for (i_list = m_list.begin(); i_list != m_list.end(); ++i_list)
     (*i_list)->draw();


    _getch();
    return 0;
}

3 个答案:

答案 0 :(得分:4)

你可以:

HACKISH:删除谓词中的对象。

恼人:远离remove_if并自行实现它所做的一切,除了添加删除。

更好:使用RAII对象而不是原始指针。换句话说,某种智能ptr。

答案 1 :(得分:1)

此时实现的方式,您将无法删除为这些对象分配的内存。通常,当您拥有指向动态分配内存的指针容器时,需要花费一些额外的精力来执行内存清理。这是一种方法:

// Assume there's a predicate function called ShouldRemove(int value);
list<int> my_list;

// initialization...

for (list<int>::iterator itr = my_list.begin(); itr != my_list.end(); ) {
    if (ShouldRemove(**itr)) {
        delete *itr;
        itr = my_list.erase(itr);
    } else {
        ++itr;
    }
}

但是正如Noah Roberts所指出的那样,如果你将你的指针存储为智能指针,那就更容易处理了。

答案 2 :(得分:1)

Standalone remove_if从不调整集合的大小并返回指向谓词为false的第一个对象的迭代器。 因此,它更适合您的任务。