2011-01-13 7 views
0

次の例では、pr2の適用がtrueを返す範囲のいくつかの要素をリストから削除します。remove_ifの後の空きメモリ

m_list.remove_if(pr2(*tmp_list)); 

私がそれを作成したとき、私は「新しい」(新CRectangleを())を使用becase上記削除された、このオブジェクトを、削除する必要があるように思えます。どのように私はこれを行うことができますか? 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

ww。それは恐ろしいことだ。 –

答えて

4

さてあなたは可能性:

ハック:述語内のオブジェクトを削除します。

ANNOYING:remove_ifから離れ、削除を追加する以外はすべて自分で実行します。

BETTER:RAWオブジェクトではなくRAIIオブジェクトを使用します。他の言葉でスマートなptrのいくつかの並べ替え。

+2

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

しかし、ノア・ロバーツが指摘したように、これは自分の後にクリーンアップあなたのポインタを保存する場合などスマートポインタに対処するために、すべての方がはるかに簡単です:ここでそれを行うための一つの方法です。

1

スタンドアロンremove_ifは、コレクションのサイズを決して変更せず、述語がfalseの最初のオブジェクトを指すイテレータを返します。したがって、それはあなたの仕事にとってより適切です。

関連する問題