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

C++ mutable 키워드란? const 객체에서도 값 변경하기

C++에는 다양한 저장 클래스(storage class)가 존재하며, 그중 하나가 바로 mutable입니다. mutable로 선언된 데이터 멤버는 객체가 const 타입이라 하더라도 언제든지 값을 변경할 수 있습니다. 즉, 여러 멤버 중 일부만 수정 가능하게 두고 나머지는 상수처럼 보호하고 싶을 때 mutable을 활용하면 매우 유용합니다.

그렇다면 실제 코드에서 어떻게 동작하는지 예제를 통해 살펴보겠습니다.

예제 코드

#include <iostream>
using namespace std;
class MyClass{
    int x;
    mutable int y;
    public:
    MyClass(int x=0, int y=0){
        this->x = x;
        this->y = y;
    }
    void setx(int x=0){
        this->x = x;
    }
    void sety(int y=0) const { // 멤버 함수는 const이지만, mutable 멤버는 값 변경 가능
        this->y = y;
    }
    void display() const{
        cout<<endl<<"(x: "<<x<<" y: "<<y << ")"<<endl;
    }
};
int main(){
    const MyClass s(15,25); // const 객체 생성
    cout<<endl <<"Before Change: ";
    s.display();
    s.setx(150);
    s.sety(250);
    cout<<endl<<"After Change: ";
    s.display();
}

실행 결과 (컴파일 오류)

[Error] passing 'const MyClass' as 'this' argument of 'void MyClass::setx(int)' discards qualifiers [-fpermissive]

오류가 발생한 이유

위 코드를 그대로 실행하면 컴파일 오류가 발생합니다. sconst MyClass 타입의 객체이기 때문에, x 멤버를 수정하려는 setx() 함수를 호출할 수 없습니다. const 객체는 비상수(non-const) 멤버 함수를 호출할 수 없기 때문입니다.

setx 호출 제거 후 실행 결과

반면 s.setx(150); 라인을 제거하고 실행하면 어떻게 될까요?

Before Change:
(x: 15 y: 25)
After Change:
(x: 15 y: 250)

결과 분석

흥미로운 점은 y의 값이 25에서 250으로 성공적으로 변경되었다는 것입니다. sety() 함수는 const 멤버 함수임에도 불구하고 y를 수정할 수 있었는데, 이는 ymutable로 선언되어 있기 때문입니다.

정리하면 다음과 같습니다.

  • const 객체: 일반 멤버 변수(x)는 어떤 방법으로도 수정할 수 없습니다.
  • mutable 멤버(y): const 객체 안에서도, const 멤버 함수 내부에서도 자유롭게 값을 변경할 수 있습니다.

이러한 특성 덕분에 mutable은 캐시(cache), 뮤텍스(mutex), 디버깅용 카운터 등 객체의 논리적 상태에는 영향을 주지 않으면서 내부적으로 갱신이 필요한 멤버를 구현할 때 널리 사용됩니다.