Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++에서 사용자 정의 클래스를 키로 사용하는 unordered_map 만드는 방법

이 글에서는 C++에서 사용자 정의 클래스(user-defined class)를 키(key)로 사용하는 unordered_map을 생성하는 방법을 알아봅니다.

unordered_map은 내부적으로 해시 테이블을 기반으로 동작하기 때문에, 기본 자료형(int, string 등)이 아닌 사용자 정의 클래스를 키로 사용하려면 다음 두 가지 요소가 반드시 필요합니다.

  • 동등성 비교 연산자(operator==): 해시 충돌이 발생했을 때 두 키가 실제로 같은지 비교하기 위해 필요합니다.
  • 사용자 정의 해시 함수: 클래스 객체를 size_t 타입의 해시 값으로 변환하는 함수로, 템플릿의 세 번째 인자로 전달합니다.

예제 코드

#include <bits/stdc++.h>
using namespace std;

// 키 값으로 사용할 클래스 객체
struct Person {
    string first, last;
    Person(string f, string l){
        first = f;
        last = l;
    }
    bool operator==(const Person& p) const{
        return first == p.first && last == p.last;
    }
};

class MyHashFunction {
public:
    // 이름 길이의 합을 해시 값으로 사용
    size_t operator()(const Person& p) const{
        return p.first.length() + p.last.length();
    }
};

int main(){
    unordered_map<Person, int, MyHashFunction> um;
    Person p1("kartik", "kapoor");
    Person p2("Ram", "Singh");
    Person p3("Laxman", "Prasad");
    um[p1] = 100;
    um[p2] = 200;
    um[p3] = 100;
    for (auto e : um) {
        cout << "[" << e.first.first << ", "<< e.first.last<< "] => " << e.second << '\n';
    }
    return 0;
}

실행 결과

[Laxman, Prasad] => 100
[kartik, kapoor] => 100
[Ram, Singh] => 200

코드 설명

Person 구조체는 이름(first)과 성(last)을 멤버 변수로 가지며, operator==를 오버로딩하여 두 객체가 같은 사람인지 비교할 수 있도록 합니다. 이 연산자가 없으면 해시 충돌 시 키의 동등성을 판단할 수 없어 컴파일 오류가 발생합니다.

MyHashFunction 클래스는 operator()를 정의하여 Person 객체의 이름과 성 길이의 합을 해시 값으로 반환합니다. 이렇게 만든 해시 함수 클래스를 unordered_map<Person, int, MyHashFunction>처럼 세 번째 템플릿 인자로 지정하면 됩니다.

다만 이름 길이의 합처럼 단순한 해시 함수는 서로 다른 객체가 동일한 해시 값을 가지는 해시 충돌이 자주 발생할 수 있습니다. 실무에서는 문자열의 각 문자를 활용하거나 표준 해시 알고리즘을 조합하는 등 충돌 가능성을 낮추는 해시 함수를 설계하는 것이 좋습니다.