2009-12-25 3 views
0

내가 여기, 코드를 이해하려고 노력하고 혼란을 조각의 원인이되는 :단항 포인터 증가는

typedef map<int, Person, less<int> > people_map; 
people_map people; 
. 
. 
. 
cout << "Erasing people of age 100" << endl; 

    for (people_map::iterator j = people.begin(); j != people.end();) { 
     if (j->second.GetAge() == 100) 
     { 

      people.erase(j++); // iterator is advanced before the erase occurs 

     } 
     else 
      ++j; // advance the iterator 
    } // end of erase loop 

혼란은 다음과 같습니다 난 후 J를 증가하려면 세그먼트 화 오류를 일으키는 함수 호출. 나는 이런 식으로 변경

:

if (j->second.GetAge() == 100) 
     { 
      temp = j++; 
      j--; 
      people.erase(j); // iterator is advanced before the erase occurs 
      j=temp; 

     } 

원인이 오류를 세그멘테이션 이유를 이해할 수 없습니다입니다.

또는 같은

:

if (j->second.GetAge() == 100) 
     { 
      people.erase(j); // iterator is advanced before the erase occurs 
      j++; 
     } 

는 세그먼트 오류가 발생합니다. 후위 증가를 사용하는 이유는,

// disable warnings about long names 
#ifdef WIN32 
#pragma warning(disable : 4786) 
#endif 

#include <string> 
#include <map> 
#include <algorithm> 
#include <iostream> 
#include <sstream> 
#include <iterator> 
#include <functional> 

using namespace std; 

class Person { 
    // private members 
    string m_sName; 
    string m_sEmail; 
    int m_iAge; 

public: 

    // constructor 

    Person(const string sName, 
      const string sEmail, 
      const int iAge) : 
    m_sName(sName), m_sEmail(sEmail), m_iAge(iAge) { 
    }; 

    // default constructor 

    Person() : m_iAge(0) { 
    }; 

    // copy constructor 

    Person(const Person & p) : 
    m_sName(p.m_sName), m_sEmail(p.m_sEmail), m_iAge(p.m_iAge) { 
    }; 

    // operator = 

    Person & operator=(const Person & rhs) { 
     // don't assign to self 
     if (this == &rhs) 
      return *this; 

     m_sName = rhs.m_sName; 
     m_sEmail = rhs.m_sEmail; 
     m_iAge = rhs.m_iAge; 
     return *this; 
    }; 

    // access private members 

    string GetName() const { 
     return m_sName; 
    }; 

    string GetEmail() const { 
     return m_sEmail; 
    }; 

    int GetAge() const { 
     return m_iAge; 
    }; 

}; // end of class Person 

// function object to print one person 

class fPrint { 
    ostream & m_os; 

public: 

    // constructor - remember which stream to use 

    fPrint(ostream & os) : m_os(os) { 
    }; 

    // person object arrives as a pair of key,object 

    void operator() (const pair <const int, const Person> & item) const { 
     m_os << "# " << item.first << " - name: " 
       << item.second.GetName() 
       << " - " << item.second.GetEmail() 
       << ", age " << item.second.GetAge() 
       << endl; 
    }; 

}; // end of class fPrint 

// declare type for storing people (numeric key, person object) 
typedef map<int, Person, less<int> > people_map; 

int main(void) { 
    // make a map of people 
    people_map people; 

    // add items to list 
    people [1234] = Person("Nick", "[email protected]", 15); 
    people [4422] = Person("Fred", "[email protected]", 100); 
    people [88] = Person("John", "[email protected]", 35); 
    // insert a different way ... 
    people.insert(make_pair(42, Person("Abigail", "[email protected]", 22))); 

    // best to declare this on its own line :) 
    fPrint fo(cout); // instance of function output object 

    // print everyone (calls a function object to print) 
    cout << "Printing all using fPrint ..." << endl; 
    for_each(people.begin(), people.end(), fo); 

    // find someone by key 
    cout << "Finding person 4422 ..." << endl; 

    people_map::const_iterator i = people.find(4422); 

    if (i == people.end()) 
     cout << "Not found." << endl; 
    else { 
     fo(*i); // dereference and print 

     // another way of printing - 

     // key itself is the "first" part of the map pair ... 
     cout << "Found key = " << i->first << endl; 

     // person object is the "second" part of the map pair... 

     cout << "Found name = " << i->second.GetName() << endl; 
    } 

    // Note, this will not work: 
    // fPrint (cout) (*i); 

    // However this will: 
    // 0, fPrint (cout) (*i); 

    // However I think the extra zero is a bit obscure. :) 

    // An alternative way of finding someone. 
    // Note - this will add them if they are not there. 
    // Since this is a reference changing it will change the person in the 
    // map. Leave off the & to get a copy of the person. 

    Person & p = people [1234]; 

    cout << "Person 1234 has name " << p.GetName() << endl; 

    // Example of erasing an element correctly ... 
    // If we did the j++ as part of the for loop we would end up 
    // adding 1 to an iterator that pointed to an element that was 
    // removed which would lead to a crash. See Josuttis p 205. 

    cout << "Erasing people of age 100" << endl; 

    for (people_map::iterator j = people.begin(); j != people.end();) { 
     if (j->second.GetAge() == 100) 
     { 

      people.erase(j++); // iterator is advanced before the erase occurs 

     } 
     else 
      ++j; // advance the iterator 
    } // end of erase loop 


    // now display who is left 
    cout << "Printing people left after erase ..." << endl; 
    for_each(people.begin(), people.end(), fo); 

    return 0; 
} // end of main 
+0

:

나는 후행 증가의 임시 결과를 사용하지 않는 것을 제외하고, 기능적으로 작동 코드와 동일하다, 당신은 또한 다음과 같이 그것을 할 수도있을 것 같군요 http://stackoverflow.com/questions/596162/can-you-remove-elements-from-a-stdlist-while-iterating-through-it – Anna

답변

1

erase는 지워진 요소에 대한 반복기를 무효화합니다.

if (j->second.GetAge() == 100) 
     { 
      temp = j++; 
      j--; 
      people.erase(j); // iterator is advanced before the erase occurs 
      j=temp; 

     } 

임시 값을 j의 이전 값과 같게 설정했기 때문에 이것은 작동하지 않습니다. 따라서 유효하지 않은 반복기를 계속 사용하게됩니다. 사후 증가의 결과는 피연산자의 원래 값입니다. 나는 그것이 중복 생각

if (j->second.GetAge() == 100) { 
    temp = j; 
    ++j; 
    people.erase(temp); 
} 
+0

또한 나는 temp = ++ j를 사용하여 시도했다. 예상대로 작동했습니다! – sachin

1

지우기 당신의 반복자를 무효화 :

여기에 전체 프로그램 목록입니다. 고급 반복기를 지우지 않고 현재 반복기를 전달하지만 부작용으로 진행됩니다.

people_map::iterator erase_it = j++; 
people.erase(erase_it); 

후위 증가에 문제가 있습니다. 따라서 시도가 실패한 것입니다.

int i = 1; 
int j = i++; // j == 1, i == 2