[C++] STL List erase member function 사용 시 주의점

반응형
반응형

* 다음 포스팅은 STL List Container의 erase 멤버 함수를 사용 시 발생할 수 있는 오류에 대해 다룹니다.

* 개인적인 공부 내용을 기록하는 용도로 작성한 글 이기에 잘못된 내용을 포함하고 있을 수 있습니다.

 

Related

→ STL List Container 사용 방법 정리


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 함수를 사용 시 유의해야할 점에 대해서 살펴 보았습니다.

도움이 되셨다면 하단의 공감 한 번씩 부탁드립니다!

반응형

댓글

Designed by JB FACTORY