-
std::remove_if, std::erase개발/C·C++ 2024. 8. 17. 20:18
이 둘을 이용해서 데이터를 지우는 로직은 보통 다음과 같다.
auto it = std::remove_if(data_vector_.begin(), data_vector_.end(), [remove_node](const std::unique_ptr<Node<UserData>>& node) { return node.get() == remove_node; }); if (it != data_vector_.end()) { data_vector_.erase(it, data_vector_.end()); }
remove_if의 구현 방식은 대단히 간단한데 다음과 같다.(참고링크)
template<class ForwardIt, class UnaryPred> ForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPred p) { first = std::find_if(first, last, p); if (first != last) for (ForwardIt i = first; ++i != last;) if (!p(*i)) *first++ = std::move(*i); return first; }
챗 지피티의 이상한(?) 설명 때문에 이해하는데 어려움이 잠깐 있었다.
- 주어진 범위(이 경우 data_vector_의 시작과 끝)에서 조건자(예를 들어 람다 함수)를 사용하여, 조건을 만족하는 모든 요소를 컨테이너의 끝으로 이동시킵니다.
- 이동된 요소는 새로운 끝 부분에 위치하며, 원래의 요소들은 이동한 후의 위치에 남아 있습니다.이 설명과 실제 구현 코드는 전혀 일치하지 않는다. 지워야 하는 요소를 컨테이너 끝으로 이동시킨다니? 내가 chat gpt를 3개월 정도 구독하다가 끊은 이유다. 틀렸는데 당당해서 열받. 이 함수는 삭제 요소를 기존 요소로 덮어 씌우면서 데이터를 앞으로 이동시킨다. 그러니 결과적으로 지워야할 데이터는 사라지게 되며 앞으로 이동시킨 만큼 뒤에 남아 있는(원본 데이터였던) 데이터를 날려서 삭제 로직이 완성된다. 뒤로 보내는 로직 같은 건 없다.
간단한 예를 들자면 [A][B][C][D] 순서의 데이터가 있을 때 A를 지운다고 하면 [B][C][D][D]로 데이터가 가공되며 반환되는 반복자의 위치는 마지막 D가 된다. [A][B][A][C][D]의 데이터에서 A를 지운다고 하면 결과적으로 [B][C][D][C][D]으로 데이터가 가공되고 반환되는 반복자는 뒤에서 두 번째 C를 가리킨다. 그래서 이 반복자를 이용해 erase 함수를 이용해서 컬렉션의 end()까지 데이터를 지우는 것이다.
'개발 > C·C++' 카테고리의 다른 글
[사소한 테스트] 곱셉/나머지 연산의 로직을 덧셈/뺄셈으로 변경한다면? (1) 2024.08.28 [윈도우 시스템 프로그래밍] 압축 파일 복사하기 (0) 2024.08.27 전화번호 무작위 생성 (0) 2024.08.03 [정렬] 더미 노드와 병합 정렬 (0) 2024.07.18 [디스어셈블리 코드] 간단한 메서드 호출과 동작을 해석해보자 (0) 2024.07.13