2017-10-15 15 views
1

해당 벡터 요소의 account_name에 따라 listAccounts에서 벡터 요소를 제거하는 함수를 작성하려고합니다. 나는이 쓴 :반복자를 사용하여 객체 유형의 벡터 요소 제거하기 C++

void Account::remove_account(string name) { 

    auto iter = listAccounts.begin(); 

    for (; iter != listAccounts.end(); iter++) { 
     if ((*iter).account_name == name) { 
      listAccounts.erase(iter); 
     } 
    } 

} 

하지만 나는 그것이 내가이 액세스 할 수없는 메모리에 접근하려한다는 것을 의미 이해하는 것과 벡터 제거에서 세그먼트 오류를 ​​받고 있어요,하지만 난 잘 모르겠어요 이것을 정확하게 쓰는 법.

+1

하나의 요소 또는 주어진 값의 모든 요소 만 제거 하시겠습니까? –

+0

중복은 첫 번째 지우기 후에 for 루프가 유효하지 않게 된 것을 설명합니다. if 문에는'break;'가 필요하다. –

+1

@Vlad from Moscow name.name과 동일한 account.name을 가진 벡터의 한 요소. –

답변

2

반복기가 가리키는 요소를 지우면 해당 반복기가 유효하지 않게됩니다. (std::vector의 경우 지워진 요소 이후의 다른 모든 반복기도 무효화됩니다). 그리고 또는 역 참조 잘못된 반복기가 정의되지 않은 동작을 증가시킵니다.

당신이 할 수있는

(제거 할 하나의 요소이다 가정) : 여러 요소에 대한

void Account::remove_account(string name) { 
    auto iter = std::find_if(listAccounts.begin(), listAccounts.end(), 
       [&](const auto& s){ return s.account_name == name; }); 
    if(iter != listAccounts.end()) 
     listAccounts.erase(iter); 
} 

, 즉 것입니다 :

void Account::remove_account(string name) { 
    for(auto iter = listAccounts.begin(); iter != listAccounts.end();){ 
     iter = std::find_if(iter, listAccounts.end(), 
        [&](const auto& s){ return s.account_name == name; }); 
     if(iter != listAccounts.end()) 
      iter = listAccounts.erase(iter); 
    } 
} 
0

당신이 다음 하나 개의 요소를 제거하려는 경우 쓸 수 있습니다

bool Account::remove_account(std::string &name) 
{ 
    auto it = std::find_if(listAccounts.begin(), 
          listAccounts.end(), 
          [&](const auto &item) 
          { 
           return item.account_name == name; 
          }); 

    bool success = it != listAccounts.end(); 

    if (success) listAccounts.erase(it); 

    return success; 
} 

코드에 대해서는이 문장 다음에

listAccounts.erase(iter); 

반복기가 유효하지 않게됩니다. 그래서 당신은 그것을 증가시킬 수 없습니다.

2

컨테이너가 수정되면 반복기가 유효하지 않게됩니다. 두 가지 좋은 해결책이 있습니다.

void Account::remove_account(const string& name) { 
    auto iter = listAccounts.begin(); 

    while iter != listAccounts.end()) { 
     if (iter->account_name == name) { 
      iter = listAccounts.erase(iter); 
     } else { 
      ++iter; 
     } 
    } 
} 

// or 
void Account::remove_account(const string& name) { 
    listAccounts.erase(
     std::remove_if(std::begin(listAccounts), std::end(listAccounts), 
         [&name](const auto& item) { 
          return item.account_name == name; 
         }), 
     std::end(listAccounts)); 
} 
+0

두 번째 솔루션에서는 벡터에서 '제거'를 호출합니다. 나는 네가 '지우기'를 의미했다고 생각한다. – navyblue

+0

예, 맞습니다. –