지피지기 백전백퇴

Cpp로 코드 깔끔하게 짜기 힘들다


문제

#include <unordered_map>

using namespace std;

unordered_map<int, int> S;

요런 코드에서 value가 0인 모든 엔트리를 제거하고 싶다면 어떻게 해야 할까?

실패의 기록

다음과 같은 코드를 짜다가 현타가 왔다.

for (auto &it: S) {
  if (it.second == 0) {
    S.erase(it);
    continue;
  }
}

S.erase(it) 하고나서 continue하면 다음 iteration으로 넘어가는건 use-after-free 아닌가, 그럼 S.erase(it++) 해야하나? 근데 거기서 continue하면 it++이후에 체크없이 continue하니까 0 entry가 두개 연속 있을때 두번째 엔트리는 체크하지 않는 버그가 생기잖아?

그거 피하려면 이렇게 해야하나?

for (auto &it: S) {
  while(it.second == 0) {
    S.erase(it++);
  }
}

이러면 it가 이미 S.end()에 도달한 경우엔 빠져나와야 할텐데? 그럼 이렇게 해야하나?

for (auto &it: S) {
  while(it != S.end() && it.second == 0) {
    S.erase(it++);
  }
  if (it == S.end()) {
    break;
  }
}

해결?

AI에게 깔끔한 코드를 작성해보라고 하니 이런 코드를 준다.

for (auto it = S.begin(); it != S.end(); ) {
  if (it->second == 0) {
    it = S.erase(it);
  } else {
    ++it;
  }
}

흠… 확실히 iterator 복사가 일어나지도 않고, 깔끔해지긴 했는데, for range는 못쓴다는게 좀 아쉽다.

간만에 알고리즘 코딩을 AI 없이 하려고 해 보니 집중도 잘 안되고 코드도 깔끔하지 못하다.