* 다음 포스팅은 STL List Container의 erase 멤버 함수를 사용 시 발생할 수 있는 오류에 대해 다룹니다.
* 개인적인 공부 내용을 기록하는 용도로 작성한 글 이기에 잘못된 내용을 포함하고 있을 수 있습니다.
Related
Content
#1 Vector erase member function
#2 List erase member function
#1 Vector erase member functon
STL 대부분의 Container는 지정된 iterator 위치의 원소를 삭제하는 erase 멤버 함수를 제공합니다.
이는 list 뿐 만 아니라 vector container 또한 erase 멤버 함수를 포함하고 있습니다.
다음은 1, 2, 3, 4, 5 를 원소로 가지는 int형 vector 에서 iterator로 원소 1을 가리키게 한 뒤, erase 멤버 함수를 사용해 제거한 예시입니다.
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> vec {1, 2, 3, 4, 5};
cout << "Before - ";
for(const auto& i : vec){
cout << i << " ";
}
cout << '\n';
// iterator를 사용해 vector의 첫 번째 원소인 1을 가리키게 합니다.
vector<int>::iterator it = vec.begin();
cout << "It → " << *it << '\n';
// erase member function을 사용해 iterator it이 가리키는 원소 1을 제거합니다.
vec.erase(it);
cout << "After - ";
for(const auto& i : vec){
cout << i << " ";
}
cout << '\n';
return 0;
}
[Result]
Before - 1 2 3 4 5
It → 1
After - 2 3 4 5
여기서 의문이 하나 생깁니다. 그렇다면 vector의 첫 번째 원소 1을 가리키고 있던 iterator는 현재 어떤 위치를 가리키게 될까요?
위에서 제시한 예시 코드에서 다음 한 줄을 추가해 현재 iterator가 가리키고 있는 값을 출력해 보도록 하겠습니다.
cout << "It → " << *it << '\n';
[Result]
Before - 1 2 3 4 5
It → 1
After - 2 3 4 5
It → 2
iterator는 자동으로 vector의 다음 원소를 가리키게 됩니다.
#2 List erase memeber function
이번에는 List Container에서 erase member function을 사용해 보도록 하겠습니다.
#include <iostream>
#include <list>
using namespace std;
int main() {
list<int> myList{1, 2, 3, 4, 5};
cout << "Before - ";
for (const auto &i : myList) {
cout << i << " ";
}
cout << '\n';
// iterator를 사용해 list의 첫 번째 원소인 1을 가리키게 합니다.
list<int>::iterator it = myList.begin();
cout << "It → " << *it << '\n';
// erase member function을 사용해 iterator it이 가리키는 원소 1을 제거합니다.
myList.erase(it);
cout << "After - ";
for (const auto &i : myList) {
cout << i << " ";
}
cout << '\n';
cout << "It → " << *it << '\n';
return 0;
}
[Result]
Before - 1 2 3 4 5
It → 1
After - 2 3 4 5
It → 1
vector와 달리 list의 iterator가 가리키는 값은 전혀 엉뚱한 값이 출력됩니다.
iterator가 이미 지워진 원소인 1의 주소를 참조하고 있는 것을 확인할 수 있습니다.
C++ STL list의 공식 문서의 Return Value 부분을 보면 다음과 같이 설명합니다.
Iterator following the last removed element.
- 마지막으로 제거된 원소의 다음 원소를 리턴합니다.
즉, list에서 erase 함수를 사용할 시 vector와 달리 이터레이터로 다음과 같이 리턴값을 받아 주어야 합니다.
// erase member function을 사용해 iterator it이 가리키는 원소 1을 제거합니다.
it = myList.erase(it);
이제 다시 코드를 실행해 보도록 하겠습니다.
#include <iostream>
#include <list>
using namespace std;
int main(){
list<int> myList {1, 2, 3, 4, 5};
cout << "Before - ";
for(const auto& i : myList){
cout << i << " ";
}
cout << '\n';
// iterator를 사용해 list의 첫 번째 원소인 1을 가리키게 합니다.
list<int>::iterator it = myList.begin();
cout << "It → " << *it << '\n';
// erase member function을 사용해 iterator it이 가리키는 원소 1을 제거합니다.
it = myList.erase(it);
cout << "After - ";
for(const auto& i : myList){
cout << i << " ";
}
cout << '\n';
// 추가된 코드
cout << "It → " << *it << '\n';
return 0;
}
[Result]
Before - 1 2 3 4 5
It → 1
After - 2 3 4 5
It → 2
이터레이터가 삭제된 원소 1이 아닌 2를 가리키고 있습니다.
이처럼 list container에서 erase 함수를 사용할 경우 반드시 iterator로 리턴값을 받아 주어야 합니다.
그렇지 않으면 iterator가 엉뚱한 값을 가리키게 되어 segmentation fault 와 같은 에러를 발생시킬 수 있습니다.
이번 포스팅 에서는 list container 에서 erase 함수를 사용 시 유의해야할 점에 대해서 살펴 보았습니다.
도움이 되셨다면 하단의 공감 한 번씩 부탁드립니다!
'Archive2 > C&C++' 카테고리의 다른 글
[C++] STL map vs multimap (feat. multimap equal_range) (2) | 2022.09.18 |
---|---|
[C++] STL map Container 사용 방법 정리 (feat. map & [hash_map]unordered_map & multi_map) (0) | 2022.08.28 |
[C++] STL List Container 사용 방법 정리 (0) | 2022.08.15 |
[C++] vector.insert 멤버함수를 이용해 두 벡터 연결하기 (0) | 2022.07.31 |
[C++] stoi & to_string 문자열 ↔ 정수 변환 (0) | 2022.06.18 |