본문 바로가기

일상+자잘한 일

[C++] set operator 사용 시 const가 필요한 이유

백준 문제를 풀다가 신기한 것을 발견했다.

vector나 배열의 비교 연산자를 오버로딩할 때는 const가 없어도 컴파일 오류가 없었는데, set의 비교 연산자를 오버로딩하려고 하니 const가 없을 때만 컴파일 오류가 나는 것을 확인했다.

 

내가 짠 코드는 아래와 같다. 분명 로컬 vscode에서는 이상 없이 컴파일 됐는데 컴파일 오류가 나서 당황스러웠다.

#include <iostream>
#include <set>
using namespace std ;

struct cmp
{
	//여기 const가 없으면 컴파일 오류가 났다.
    bool operator()(string a, string b) const {
        if(a.length() == b.length()) return a < b ;
        return a.length() < b.length() ;
    }
};

int main()
{
    int N ;
    cin >> N ;
    set<string, cmp> s ;
    string str ;

    for(int i = 0 ; i < N ; i++) {
        cin >> str ;
        s.insert(str) ;
    }

    for(auto str : s)
        cout << str << "\n" ;
}

조사해보니 이유는 단순한데 set의 member는 모두 const로 선언되서다.

set의 경우 red-black tree 구조로 되어있고 삽입과 동시에 순서를 정렬한다. 이러한 자료구조 때문에 안에 데이터가 변경되면 어떻게 변경되었는지 확인하기 어렵고 수정도 까다롭기 때문에 멤버 변수의 값 변경을 막기 위해 const로 선언되어있다.

 

따라서 operator를 멤버함수로 정의하기 위해 const가 필수적으로 필요하며 없으면 오류가 나는 것이다.

 

[참고 자료]

 

Why STL <set> the overload operator < function must be a const function?

class Test { public: int v; Test(int s) { v = s; } bool operator < (const Test & b) const { return v < b.v; } }; int main() { set <T...

stackoverflow.com

 

https://cplusplus.com/reference/set/set/

difference_typea signed integral type, identical to: iterator_traits ::difference_type usually the same as ptrdiff_t

cplusplus.com

 

std::set<Key,Compare,Allocator>::set - cppreference.com

(1) set(); (until C++11) set()    : set(Compare()) {} (since C++11) explicit set( const Compare& comp,               const Allocator& alloc = Allocator() ); (2) explicit set( const Allocator& alloc ); (3) (since C++11) template< class InputIt > se

en.cppreference.com