2011-01-13 4 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

ww. 그건 정말 나쁘다. –

답변

4

당신이 할 수 음 :

HACKISH : 술어에서 개체를 삭제합니다.

ANNOYING : remove_if에서 벗어나서 삭제를 추가하는 것 외에는 모든 것을 구현하십시오.

BETTER : 원시 포인터가 아닌 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 인 첫 번째 개체를 가리키는 반복자를 반환합니다. 따라서 작업에 더 적합합니다.

관련 문제