이 글에서는 C++ STL의 list::pop_front()와 list::pop_back() 함수의 동작 원리, 문법, 그리고 실제 코드 예제를 자세히 알아봅니다.
STL에서 리스트(List)란 무엇인가?
리스트(List)는 시퀀스의 어느 위치에서든 상수 시간(O(1)) 안에 삽입과 삭제를 수행할 수 있는 자료구조입니다. 리스트는 내부적으로 이중 연결 리스트(doubly linked list)로 구현되어 있으며, 메모리를 비연속적으로 할당할 수 있습니다.
이러한 구조 덕분에 리스트는 배열(array), 벡터(vector), 덱(deque)보다 컨테이너 내 임의 위치에서 요소를 삽입·추출·이동하는 작업에서 훨씬 뛰어난 성능을 보입니다. 반면, 특정 요소에 대한 직접 접근(random access)은 느린 편입니다.
리스트는 forward_list와 비슷하지만, forward_list는 단일 연결 리스트(singly linked list)로 구현되어 있어 앞쪽(forward) 방향으로만 순회할 수 있다는 차이가 있습니다.
list::pop_front()란?
list::pop_front()는 C++ STL의 내장 함수로, <list> 헤더 파일에 선언되어 있습니다. 이 함수는 리스트 컨테이너의 맨 앞에 있는 요소를 제거(pop)하는 데 사용됩니다.
pop_front()를 호출하면 컨테이너의 첫 번째 요소가 삭제되고, 바로 다음 요소가 새로운 첫 번째 요소가 됩니다. 이때 컨테이너의 크기(size)는 1만큼 감소합니다.
문법(Syntax)
list_container1.pop_front();
매개변수(Parameters)
이 함수는 별도의 매개변수를 받지 않습니다.
반환값(Return Value)
이 함수는 아무 값도 반환하지 않습니다. (반환 타입: void)
예제
입력: list<int> List_container = {10, 11, 13, 15};
List_container.pop_front();
출력:
List = 11 13 15
위 예제에서 pop_front() 호출 후 맨 앞의 요소 10이 제거되고, 11이 새로운 첫 번째 요소가 된 것을 확인할 수 있습니다.
실전 코드 예제
#include <iostream>
#include <list>
using namespace std;
int main(){
list<int> myList_1 = {}, myList_2 = {};
myList_1.push_front(10);
myList_1.push_front(20);
myList_1.push_front(30);
myList_1.push_front(40);
myList_1.push_front(50);
// myList_1이 빌 때까지 앞 요소를 꺼내 myList_2의 앞에 삽입
while (!myList_1.empty()){
myList_2.push_front(myList_1.front());
myList_1.pop_front();
}
cout << "Elements in the list are : ";
for (auto i = myList_2.begin(); i != myList_2.end(); ++i)
cout << ' ' << *i;
}
실행 결과
위 코드를 실행하면 다음과 같은 출력이 생성됩니다.
Elements in the list are : 10 20 30 40 50
myList_1에는 push_front()로 인해 50, 40, 30, 20, 10 순서로 저장되어 있지만, pop_front()와 push_front()를 조합해 요소를 옮기면서 원래 순서(10, 20, 30, 40, 50)가 복원된 것을 볼 수 있습니다.
list::pop_back()란?
list::pop_back() 역시 C++ STL의 내장 함수로, <list> 헤더 파일에 선언되어 있습니다. 이 함수는 리스트 컨테이너의 맨 뒤(마지막)에 있는 요소를 제거(pop)하는 데 사용됩니다.
pop_back()을 호출하면 마지막 요소가 삭제되고, 그 앞에 있던 요소가 새로운 마지막 요소가 됩니다. 이때 컨테이너의 크기는 1만큼 감소합니다.
문법(Syntax)
list_container.pop_back();
매개변수(Parameters)
이 함수는 별도의 매개변수를 받지 않습니다.
반환값(Return Value)
이 함수는 아무 값도 반환하지 않습니다. (반환 타입: void)
예제
입력: list<int> List_container = {10, 11, 13, 15};
List_container.pop_back();
출력:
List = 10 11 13
pop_back() 호출 후 맨 뒤의 요소 15가 제거되고, 13이 새로운 마지막 요소가 됩니다.
실전 코드 예제
#include <iostream>
#include <list>
using namespace std;
int main(){
list<int> myList_1 = {}, myList_2 = {};
myList_1.push_front(10);
myList_1.push_front(20);
myList_1.push_front(30);
myList_1.push_front(40);
myList_1.push_front(50);
// myList_1이 빌 때까지 뒤 요소를 꺼내 myList_2의 앞에 삽입
while (!myList_1.empty()){
myList_2.push_front(myList_1.back());
myList_1.pop_back();
}
cout << "Elements in the list are : ";
for (auto i = myList_2.begin(); i != myList_2.end(); ++i)
cout << ' ' << *i;
}
실행 결과
위 코드를 실행하면 다음과 같은 출력이 생성됩니다.
Elements in the list are : 50 40 30 20 10
myList_1의 뒤에서부터 요소를 하나씩 꺼내 myList_2의 앞에 삽입했기 때문에, 최종적으로 역순(50, 40, 30, 20, 10)으로 출력됩니다.
정리: pop_front() vs pop_back()
두 함수 모두 리스트의 크기를 1 줄이며, 매개변수와 반환값이 없다는 공통점이 있습니다. 결정적인 차이는 제거하는 위치로, pop_front()는 리스트의 첫 번째 요소를, pop_back()은 마지막 요소를 제거합니다. 두 함수 모두 이중 연결 리스트 기반이므로 O(1)의 상수 시간 안에 수행됩니다. 단, 빈(empty) 리스트에 호출하면 정의되지 않은 동작(undefined behavior)이 발생할 수 있으므로, 호출 전에 empty()로 리스트가 비어 있는지 먼저 확인하는 것이 안전합니다.