이 글에서는 C++에서 사용자 정의 클래스(user-defined class) 또는 구조체(struct)를 요소로 가지는 unordered_set을 생성하는 방법을 단계별로 살펴보겠습니다.
unordered_set은 내부적으로 해시 기반으로 동작하기 때문에, 기본 자료형(int, string 등)이 아닌 사용자 정의 타입을 저장하려면 두 가지가 반드시 필요합니다.
- 동등성 비교 연산자(
operator==): 두 객체가 같은지 판단하는 기준을 정의해야 합니다. - 사용자 정의 해시 함수: 객체를 해시 값으로 변환하는 규칙을 직접 제공해야 합니다.
즉, 먼저 비교 대상이 될 구조체 타입을 정의하고, 그다음 두 객체를 비교할 수 있는 함수와 해시 값을 계산할 함수 객체(functor)를 함께 준비하면 됩니다.
예제 코드
#include <bits/stdc++.h>
using namespace std;
// 사용자 정의 구조체
struct Test {
int id;
// 동등성 비교를 위한 연산자 오버로딩
bool operator==(const Test& t) const{
return (this->id == t.id);
}
};
// 해시 함수를 위한 클래스
class MyHashFunction {
public:
size_t operator()(const Test& t) const{
return t.id;
}
};
int main(){
Test t1 = { 110 }, t2 = { 102 }, t3 = { 101 }, t4 = { 115 };
// 사용자 정의 해시 함수를 지정하여 unordered_set 선언
unordered_set<Test, MyHashFunction> us;
us.insert(t1);
us.insert(t2);
us.insert(t3);
us.insert(t4);
for (auto e : us) {
cout << e.id << " ";
}
return 0;
}실행 결과
115 101 110 102
코드 설명
operator==오버로딩:Test구조체 내부에서id멤버 변수를 기준으로 두 객체의 동일 여부를 판단합니다. 이것이 없으면unordered_set은 중복 여부를 검사할 수 없습니다.MyHashFunction클래스:operator()를 오버로딩한 함수 객체로,id값을 그대로 해시 값으로 반환합니다. 실제 프로젝트에서는 충돌(collision)을 줄이기 위해 더 정교한 해시 로직을 사용하는 것이 좋습니다.unordered_set<Test, MyHashFunction>: 두 번째 템플릿 인자로 커스텀 해시 함수를 전달하여, 사용자 정의 타입도 해시 기반 컨테이너에 저장할 수 있게 합니다.
출력 결과를 보면 삽입 순서(110, 102, 101, 115)와 다르게 나타나는데, 이는 unordered_set이 해시 버킷 구조로 데이터를 관리하기 때문입니다. 즉, 요소의 순서는 보장되지 않으며 평균 O(1)의 시간 복잡도로 빠른 삽입·검색·삭제가 가능합니다.