👨🏻‍💻 programming/◽ c, c++

(c++20) STL::Container #1 - std::to_array, erase, erase_if

핑크코냥 2024. 6. 17. 18:01
728x90

 

"c++20 STL::Container #1"


 

1. std::to_array

 

std::array 만드는 방법이 추가되었다. 

//암시적 타입 추론 
auto ToArray = std::to_array("Hello World");
//명시적 타입 추론
auto ToArray = std::to_array<int>({ 1,2,3,4,5,6 });

 

2. std::erase, erase_if 

 

기존에 vector 데이터 중 특정한 조건에 부합하는 데이터를 삭제하려고 할 때 여러가지 방법과 문제점을 알아보자.

// 1번 ====================================================================
vector<int> vec {-1, 2, 3, 4, -5, 7, -2, 3 };
	for (auto it = vec.begin(); it != vec.end(); it++)
	{
		int value = *it;
		if (value < 0)
		{
			vec.erase(it);
		}
		else
		{

		}
	}

// error 발생 vec.erase(it); 지워진 대상 바로 다음을 가리킴. 
// 2번 ====================================================================
	for (auto it = vec.begin(); it != vec.end();)
	{
		int value = *it;
		if (value < 0)
		{
			it = vec.erase(it);
		}
		else
		{
			it++;
		}
	}
    
// 3번 ====================================================================
	std::remove_if(vec.begin(), vec.end(), [](int num) {return num < 0; });
    // 입력 : -1, 2, 3, 4, -5, 7, -2, 3
    // 결과 : 2, 3, 4, 7, 3 , 7 ,-2, 3
    
// 4번 ====================================================================
	auto newEnd = std::remove_if(vec.begin(), vec.end(), [](int num) {return num < 0; });
	vec.erase(newEnd, vec.end());

1번: Runtime Error 발생 

error: can't increment invaildated vector iterator

이유: 반복자(iterator)를 무효화(반복자 무효화 현상)한다. 반복자가 벡터의 한 원소를 가리키고 있었는데, 그 객체가 사라져 버리면 그 이후 반복자를 통해 원소에 접근하는 것이 불가능해진다. 컨테이너마다 차이가 있지만 원소의 위치가 바뀔 때 해당 원소를 가리키던 반복자가 무효화 된다. 

1번은 원소 삭제가 이뤄질 때 반복자는 더이상 유효한 객체를 가리키는 상테가 아니다. 

 

2번: 1번의 문제를 해결하는 방법

erase()는 삭제할 경우 삭제할 요소의 다음 iterator를 return하기 때문에 it에 넣어주면서 유효한 객체를 가리키는 반복자를 생성해준다. 

 

3번:

std::remove_if는 컨테이너의 크기를 변화 시키지 않는다. 조건에 만족하는 데이터를 순서대로 채우는 형식이다. 그래서 위와같은 엉뚱한 결과가 나오게 된다.

 

4번: 3번의 문제를 해결하는 방법

std::remove, std::remove_if는 해당 범위의 맨 끝을 가리키는 반복자를 리턴한다.

해당 범위 맨 끝의 반복자부터 (빨강) vector의 맨 끝 반복자 (파랑)을 erase 해준다.

이러한 불편한 점을 싹 날려줄 c++20 std::erase, erase_if 를 소개한다. 컨테이너 내장함수가 아닌 std::내장함수 이다. 

// std:: c++20 erase, erase_if 
std::erase(vec, 2);
std::erase_if(vec, [](int num) {return num < 0; });

2번과 4번과 같은 결과 값을 도출 할 수 있다. 속 시원하다 !!!

 

바이용 ~! 

1. 내용 출저: 인프런 Inflearn - Rookiss 쌤 강의인 C++20 훑어보기 중.
2.https://en.cppreference.com/w/
728x90