Skip to content


C++의 유일한(?) implicit const_cast

C++에는 (아마도 유일한) 묵시적 const_cast 가 있다. 바로,

char* str = “hello, world”;

이건 C++이 (최대한) C와의 하위 호환성을 가지려다 보니 나온 문제다. C 표준 라이브러리의 수많은 문자열 처리 함수들이 char* 을 인자로 받긴하지만, 의미 상으론 const char* 인 경우가 대부분이기 때문;

만약 const char* –> char* 을 명시적으로 바꿔야 한다면 많은 수의 C 코드가 C++ 컴파일러에서 컴파일되지 않게 된다. 그래서 이건 묵시적으로 const_cast<char*> 을 해 버린다.

하지만 모든 C 문자열 처리 함수가 const char* 의 의미로 동작하는건 아니다. 그래서 예전 버전의 Mozilla 에선 이와 관련한 버그가 있었다. 공유 문자열 버퍼를 strchr 같이 실제로 버퍼를 조작하는 함수에서 문제가 생기는 것 – const semantic이 깨지는 것.

여튼 지금 문제는 이게 아니라(…), 오전에 everclear 군이 제기한 코드;
아래와 같은 코드가 있다. 왜 성공적으로 컴파일 될까?

struct A {
int& a;
explicit A(int& _a) : a(_a) { }
A(const A& rhs) : a(rhs.a) { }
};

const A&인 rhs.a 는 const int& 가 되야 하지 않나? 비슷하게 int& a 대신 int* const a 여도 저 코드는 잘 동작한다; 대체 왜 이럴까?

이 저작물은 별도로 명시하지 않은 경우, Creative Commons Attribution-Share Alike 3.0 Unported License에 따라 이용하실 수 있습니다.

Posted in Computer.

Tagged with , .


18 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. bkangel says

    테스트 해 보니 struct의 const는 struct 자체가 const이지 내용까지 const가 되는 것은 아닌 것 같음.

    int* const a 경우는 const 대상이 value가 아니라 address라서 상관 없는 것 같고 const int* a로 하면 안될 듯?

    • rein says

      전 rhs.a 가 int* const 일 때도 const int* const 가 될 꺼라고 생각했죠(…). 형 말대로 address라 그런 듯

  2. summerlight says

    C++의 const는 해당 객체나 배열이 “실제로” 차지하는 메모리 영역에 대한 비트 수준의 상수성만을 보장하는 것으로 알고 있습니다. 저 경우는 참조만 가져오는 것은 실제 포인터만 복사하이니 입력 인자로 주어진 객체의 비트 수준 상수성을 깨지 않기 때문에 허용되는 것 같고요. 그래서 포인터나 참조에 대한 상수성을 보장하려면 const getter 함수를 만들어야 하죠 OTL

  3. Dish says

    읽으면서 자문 이후에 답을 쓰는 형식을 기대하면서 내렸는데
    자문으로 마무리 되는 포스팅이네요 ㅋㅋㅋ

    • rein says

      …앞 부분은 질문을 하기 위한 프롤로그지(???)

  4. lolisia says

    struct const의 멤버변수들은 const가 되지 않습니다. 위의 struct A로 예로 들면

    int a = 3;
    const A foo(a);
    foo.a = 4;

    위의 코드는 문제없이 작동합니다. foo는 상수지만, foo.a는 상수가 아니기 때문이죠.
    그래서 A(const A& rhs) : a(rhs.a) { } rhs.a가 상수가 아니기 때문에 컴파일이 됩니다.

    • rein says

      struct const 의 말이 잘 이해가 안가긴하는데, summerlight 님과 같은 의미인건가요?
      A* const 같은 의미라면 말이 되는데, 단순히 const 인 구조체의 멤버는 const는 아니란 말인지 좀 모호하네요;

      만약 제가 잘못 이해한거라면;

      struct A {
      int x;
      };

      const A a;
      a.x = 0; // error

      const struct 의 멤버들은 const 라 (summerlight 님의 말대로 메모리 레벨에서), 코드가 컴파일 되지 않습니다.

  5. Ntopia says

    http://pastebin.com/0KpkDS8c
    위와 같은 코드도 돌아가는 걸로 봐서는…
    rhs.a 가 int& 인것 같아요

    • rein says

      흠…저 코드만으론 verify되지 않는듯

      • Ntopia says

        헉..
        어떤 const 객체의 멤버 중에 레퍼런스가 있을 때, const 임에도 불구하고 그 멤버를 마음대로 바꿀 수 있는 건가요?? …

  6. dgoon says

    그닥 deep casting 해주진 않는듯? 그래서 const & A 인 경우에는 A::do_somthing(..) const { … } 이건 호출 가능하고, A::do_something(..) { … } 이건 불가능하고 – 이런 제한이 붙는거 아닐까? 저렇게 깊게 const casting 해주면 이런거 필요 없을 것 같은데

  7. 아라크넹 says

    이런 이유 때문에 D(2.0기준)에는 const와 invariant를 구분하고 있지요.

    • rein says

      D에선 그렇군요; 아예 이런걸 포기한 언어도 많은데(…) 왜 이렇게 어중간한지;;

  8. 세라비 says

    C99 3.9.3.3에 이런 말이 있군요. Each non-static, non-mutable, non-reference data member of a const-qualified class object is const-qualified, .

    static/mutable 멤버는 당연할텐데, reference가 그럴 거라고는 상상 못했네요.

    • rein says

      summerlight 님 말과 같은 얘기가 되겠네요. 결국 C++이 만들어주는 상수성(const-ness)의 개념이 단순한 메모리 상수성이라 표준도 일단 저러한듯 하군요;
      mutable은 변형이니 약간 다른 얘기지만요(…).



Some HTML is OK

혹은 트랙백 보내기 / or, reply to this post via trackback.