본문 바로가기
프로그래밍/C++

C++] const_cast에 대해서...

by Hwan2 2020. 6. 15.
728x90
반응형

모든 언어에는 형변환이 있습니다. C++에선 다양한 형번환 객체들을 제공합니다.


1. static_cast = https://hwan-shell.tistory.com/211


2. dynamic_cast = https://hwan-shell.tistory.com/213


3. const_cast


4. reinterpret_cast = https://hwan-shell.tistory.com/219


가 있습니다.


그 중 const_cast에 대해 알아보도록 하겠습니다.



1. const_cast란??

이름만 보면 const를 cast해 const변수를 바꾸는 그런역할을 할 것 같이 생긴 녀석입니다.
맞으면서도 다릅니다.

const_cast를 할 수 있는 조건이 있습니다.

1. const로 선언된 포인터만 const를 풀어줄 수 있다.
2. 포인터가 아닌 일반 변수의 const는 풀어줄 수 없다.
3. 함수 포인터, 맴버 함수에 대한 const는 풀어줄 수 없다.

정리해 보자면 const_cast는 const로 선언된 변수를 가르키는 포인터 변수가 있을 때,
const변수는 유지한 체 포인터만 자유롭게 풀어주는 역할을 하는걸 알 수 있습니다.
원본은 변경하지 않기 때문에 안전하지요. 하지만 원본만 안바뀌는 것이지 값을 포인터를 통해 바꾼 후
원본값을 새로운 포인터로 넘겨받는다면 바뀐 값이 넘어갑니다.(예시를 보면 알 수 있습니다.)

때문에 사용을 신중히 하는것이 좋을 것 같고 왠만하면 안쓰는게 좋을 것 같습니다.



2. const_cast 예시

1) 일반적인 error나는 상황

int main() {
    const int num = 10;
    num = 20; //error.

    const int* p = #
    *p = 20;    //error

    int* p2 = p; //error

    return 0;
}


이런식으로 const로 선언된 변수와 포인터는 해당 원본값을 변경할 수 없습니다.


2) const_cast를 이용한 값 변경

int main() {
    const int num = 10;
    const int* p = #
    int* p2 = const_cast<int*>(p);
    *p2 = 30;
    printf("&num = %x, p = %x, p2 = %x\n", &num, p, p2);
    printf("num = %d, *p = %d, *p2 = %d\n", num, *p, *p2);

    return 0;
}


이상한점이 있습니다.

p와 p2가 가르키는 값은 바뀌었고 num은 그대로 입니다.

하지만 3개 다 가르키는 주소값은 동일하지요.


어찌된 일일까요???

저도 궁금해서 뜯어봤습니다.



3) 코드를 뜯어 본 const_cast

int main() {
    const int num = 10;
    int* p = const_cast<int*>(&num);
    int i = 100;
    *p = 20;

    printf("&num = %x, p = %x, &i = %x\n", &num, p, &i);
    printf("num = %d, *p = %d, i = %d\n", num, *p, i);


    return 0;
}


const int num = 10;

int *p = const_cast<int*>(&num);

int i = 100;


이렇게 주고 디어셈블리코드를 봤습니다.


여기까지 보면 변수가 잘 이동 됩니다.

심지어 *p = 20을 만나면 num 변수 값도 20으로 표시가 됩니다.


하지만 printf를 통해 i 값을 push하는 과정에서 차이가 납니다.

밑줄친 부분이 num 값을 push하는 줄입니다.

레지스터에 값을 저장하는것 없이 막바로 10을 push해주는걸 확인할 수 있습니다.


이걸통해 생각해볼 수 있는 사실은 다음과 같습니다.


1. const_cast로 const int* 를 int *로 만든 후 값을 바꾸면 원본이 가르키고 있는 값도 바뀐다.

2. 하지만 원본을 출력을 할 때는 data영역에 올라가 있는 const 값이 그대로 출력된다.

3. 이를 통해 num값을 유추해 보자면 num이 가르키고 있는 주소값과는 별개로 num이라는 변수 자채는 본래 값을 가르키고 있는? 유지하고 있는? 매핑? 이런 비슷한 형태가 되는 것 같다고 생각해 볼 수 있다.



그림으로 그리자면 이러한 형태가 되는 것 같습니다.





실제로 const_cast로 값을 바꾼 후 새로운 const 포인터에 값을 입력받으면 바뀐 값이 입력됩니다.


int main() {
    const int num = 10;
    int* p = const_cast<int*>(&num);
    *p = 20;
    const int* z = &num;

    printf("%d\n", *z);

    return 0;
}



때문에 급할 때 아니면 사용을 자제합시다^^;;


반응형

댓글


스킨편집 -> html 편집에서