본문 바로가기
C++20/STL

[C++20 - STL] Chapter 03. Container #2 (erase, erase_if)

by song.ift 2023. 7. 28.

GitHub :https://github.com/developeSHG/CPP20-STL/commit/9a811599df744777d4644ed08ed25af813a44c55 

 

Container #2 (erase, erase_if) · developeSHG/CPP20-STL@9a81159

developeSHG committed Jul 28, 2023

github.com

 

 


 

 

중요한 개념.
C++을 사용했으면 누구나 한번쯤은 STL 컨테이너의 삭제에 대해 불편한 점을 느껴봤을 것이다.

 

#include <iostream>
using namespace std;
#include <list>
#include <vector>
#include <map>
#include <algorithm>
#include <ranges>
#include <concepts>
#include <coroutine>
#include <array>

// 오늘의 주제 : Container #2 (erase, erase_if)

int main()
{
	// 좀 중요한 개념.
	// C++을 사용했으면 누구나 한번쯤은 STL 컨테이너의 삭제에 대해 불편한 점을 느껴봤을 것이다.

	// ex) 기존 방식대로 음수를 삭제해보자.
	{
		vector<int> vec{ -1, 2, -3, 4, -5 };

		// 기존 방식
		{	
			// 밑에 삭제코드는 STL을 많이 안접해본 사람이 작성할 수 있는 코드로써
			// 처음보면 잘 삭제가 되지 않을까? 라는 생각이지만,
			// 많이 겪어본 사람들은 C++의 엄청난 함정 이라는 것을 알고있다.
			for (auto it = vec.begin(); it != vec.end(); it++)
			{
				int value = *it;
				if (value < 0)
				{
					vec.erase(it);
				}
				else
				{

				}
			}

			// 공식
			for (auto it = vec.begin(); it != vec.end();)
			{
				int value = *it;
				if (value < 0)
				{
					it = vec.erase(it); // 삭제되면 다음 iterator를 받아줘야하고, 한 개만 삭제할거면 break문을 걸어 빠져나온다.
				}
				else
				{
					++it; // for문의 ++은 iterator가 삭제되지 않았을 때만 한다. erase 하면 다음 iterator를 가리키기 때문.
				}
			}

			for (auto num : vec)
				cout << num << endl;
		}

		
		// 위의 방식들은 너무 지저분하다.
		// 다른 프로그래머들이 수정하다가 버그를 일으킬 수 도 있고, 가독성이 너무 안좋다.
		// 조금 나은 방식으로는 algorithm 함수를 이용.
		{
			std::remove_if(vec.begin(), vec.end(), [](int num) { return num < 0; });
			// 하지만 결과는 매우 이상하다. (2, 4, -3, 4, -5)
			// remove_if도 함정이다. 이름부터가 함정.
			// if를 만족하면 삭제하겠다 가 아니라, 단지 이동시켜주는 기능이다.
			// 삭제되면 안되는 애들만 복사해서 앞으로 덮어쓰고, 나머지 애들은 그냥 놔두기 때문에 값이 이상하게 나온 것.

			// 그래서 해결법은 remove_if가 뱉어주는 이터레이터 결과물을 받아주고, erase로 end까지의 범위를 삭제해줘야 정상적으로 된디.
			// 이것도 매우 불편하다.
			auto newEnd = std::remove_if(vec.begin(), vec.end(), [](int num) { return num < 0; });;
			vec.erase(newEnd, vec.end());
		}

		// C++20 erase, erase_if
		// 지저분한 방식들을 해결해주는 기능이 추가됐다. (가독성이 매우 좋음)
		{
			std::erase(vec, 2);
			std::erase_if(vec, [](int num) { return num < 0; });
		}
	}

}

댓글