C++

[C++] explicit와 mutable

hanseongbugi 2024. 12. 16. 14:44

explicit

#include <iostream>

class MyString {
    char* content;
    int contentLength;
    
    int contentCapacity;
    
public:
    MyString(int capacity); // capacity 만큼 빈배열 생성 
    
    MyString(const char* str); // str의 길이만큼 빈배열 생성 후 삽입
    
    MyString(const MyString& str); // 복사 생성자
    
    ~MyString(); // 소멸자
};
// 구현 생략

int main()
{
    MyString s(3);
}
  • 위 코드와 같이 MyString 클래스가 존재한다. 
  • 만약 아래와 같이 MyString 객체를 인자로 받는 함수가 존재하고
void DoSomethingWithString(MyString s) 
{
    // Do Something...
}
  • 아래와 같은 코드가 존재할 때 컴파일이 가능한가?
DoSomethingWithString("abc");
  • 정답은 컴파일이 가능하다.
    • C++ 컴파일러가 "abc"를 MyString으로 바꿀 수 있을지 찾아본다.
    • MyString의 생성자에는 MyString(const char* str)이 존재한다.
    • 따라서 암시적 변환(implicit conversion)을 통해 올바른 생성자로 변환이 된다.
  • 만약 암시적 변환을 이르키고 싶지 않을 경우는 어떻게 해야할까?
    • 암시적 변환이 의도한대로 이루어지지 않거나, 의도하지 않았음에도 컴파일이 될 수 있음
    • explicit 키워드를 통해 암시적 변환을 할 수 없도록 컴파일러에게 명시할 수 있음
#include <iostream>

class MyString {
    char* content;
    int contentLength;
    
    int contentCapacity;
    
public:
    explicit MyString(int capacity); // capacity 만큼 빈배열 생성 
    
    MyString(const char* str); // str의 길이만큼 빈배열 생성 후 삽입
    
    MyString(const MyString& str); // 복사 생성자
    
    ~MyString(); // 소멸자
};
// 구현 생략

int main()
{
    MyString s(3);
}
  • explicit는 해당 생성자가 복사 생성자 형태로도 호출되는 것을 막게 된다.
MyString s(5);   // 허용
MyString s = 5;  // 컴파일 오류!

mutable

  • const를 사용해 멤버 함수를 생성하면 함수 내부에서 멤버 변수들의 값을 바꾸는 것이 불가능함
#include <iostream>

class A {
    int data;
    
public:
     A(int data) : data(data) {}
     void doSomething(int x) const
     {
         data = x; // 불가능
     }
     void printData() const
     {
         std::cout << "data : " << data << std::endl;
     }
};

int main()
{
    A a(10);
    a.doSomething(3);
}
  • 위 코드를 컴파일 하게 된다면 const 멤버함수에서 assign을 하고 있다고 에러를 발생시킨다.
  • 따라서 data를 mutable로 선언해야한다.
#include <iostream>

class A {
    mutable int data;
    
public:
     A(int data) : data(data) {}
     void doSomething(int x) const
     {
         data = x; // 불가능
     }
     void printData() const
     {
         std::cout << "data : " << data << std::endl;
     }
};

int main()
{
    A a(10);
    a.doSomething(3);
    a.printData();
}
output
data : 3
  • 위 처럼 data의 값이 const 함수 안에서 바뀐 것을 알 수 있다.
  • mutable을 사용하는 것 보다 const를 때버리는 것이 효율적일 수 있다.
  • const를 사용하면 이 함수는 멤버 변수를 변경시키지 않는다는 것을 표현한다.
    • 만약, 캐쉬 메모리를 사용하는 데이터베이스가 존재한다면, 읽기 과정에서 문제가 생긴다.
    • 캐쉬 미스가 발생한다면 데이터베이스에서 값을 읽고 캐쉬에 쓰기 작업을 해야한다.
    • 이때 데이터베이스에서 값을 읽는 함수는 const로 선언되어 있다.
    • cache를 mutable로 선언하면 문제가 해결된다.
  • mutable 키워드는 const 함수 안에서 해당 멤버 변수에 const가 아닌 작업을 할 수 있게 만들어준다.

 

 

 

 

출처

https://modoocode.com/253

 

씹어먹는 C ++ - <4 - 6. 클래스의 explicit 과 mutable 키워드>

모두의 코드 씹어먹는 C ++ - <4 - 6. 클래스의 explicit 과 mutable 키워드> 작성일 : 2018-12-26 이 글은 49684 번 읽혔습니다. 에 대해 다룹니다. 안녕하세요 여러분! 이번 강좌는 클래스에서 비교적 자주 쓰

modoocode.com