2011-01-13 84 views
0

在以下示例中,我從列表中刪除pr2的應用程序返回true的範圍內的一些元素。remove_if後的空閒內存

m_list.remove_if(pr2(*tmp_list)); 

在我看來,有必要刪除該對象,這是上面取出,becase的當我創建它,我用「新」(新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; 
} 
+0

Ew。那太糟了。 – 2011-01-14 00:45:37

回答

4

嗯,你可以:

的hackish:刪除謂詞對象。

惱人:遠離remove_if並執行它自己做的所有事情,除了添加刪除。

BETTER:使用RAII對象而不是原始指針。換句話說,某種智能ptr。

+2

+1。職責分離適用於此:清理內存分配基本上是更新容器內容的單獨「責任」。 – 2011-01-14 00:01:52

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; 
    } 
} 

但正如諾亞·羅伯茨指出,這都是很容易處理,如果你保存你的指針,經過自己清理的智能指針。

1

獨立remove_if永不調整集合的大小,並返回指向謂詞爲false的第一個對象的迭代器。 因此它更適合您的任務。

相關問題