상수(const)의 정의가 궁금합니다...
글쓴이: mastr99 / 작성시간: 수, 2014/10/15 - 12:28오전
EC++ 다시 읽어보는 중에 const_cast에 대해 궁금증이 생겼습니다.
그냥 변수/객체의 상수성을 없애준다고만 알고 있었고 실제 코딩에서 사용한 적이 없어서 어물쩡 넘어갔었는데요..
int main(void) { int a = 0 ; const int &ra = a ; int &rra = const_cast<int&>(ra) ; rra = 10 ; printf( "%d\n", a ) ; /// a=10 const int b = 0 ; int &rb = const_cast<int&>(b) ; rb = 10 ; printf( "%d\n", b ) ; /// b=0 const int *pC = new int(0) ; int *ppC = const_cast<int*>(pC) ; *ppC = 10 ; printf( "%d\n", *pC ) ; /// *pC=10 ??? return 0; }
생각해보니 애초에 상수로 선언된 변수 b는 값을 바꾸는 동작 자체가 잘못되었으니
두번째 예제는 코드 자체가 잘못된 것 같고,
세번째 예제는 pC가 가르키는 값이 heap영역에 선언되었으니 값이 바뀌는 것인지...애매하구요....
그냥 const_cast의 정의를 "상수포인터", "상수레퍼런스"의 상수성을 제거한다 라고 이해하는게 맞는 것일까요?
부족한 글 읽어주셔서 감사합니다.
Forums:
C++(C가 아니라)에서 '어떤 장소에 있는 값을
C++(C가 아니라)에서 '어떤 장소에 있는 값을 바꾸지 않겠다'라는 것과 '어떤 값에 이름을 붙이겠다' 라는 의도를 구분해야 합니다.
const int b = 0; 라고 쓰면 0이라는 값에 'b'라는 이름을 붙이겠다 라고 말하는 것입니다.
* 여기에 '장소'이라는 개념은 들어가지 않습니다. *
컴파일러는 이후에 등장하는 이름 'b'를 0으로 바꿉니다.
printf( "%d\n", b ); 가 0을 출력하는 이유가 그 때문입니다.
심지어 이렇게 써도 말이죠.
int &rb = const_cast(b);
rb = 10 ;
애초에 b를 위한 '장소'는 없는데 사용자가 억지로 non-const 참조를 하라고 하니 컴파일러는 이름이 없는 장소를 하나 만들고 여기에 'b'의 값 0을 집어 넣습니다.
rb는 이를 참조하죠.
결국 위 코드는 다음과 같이 쓴 것과 동일한 효과가 있습니다.
int rb = b;
rb = 10;
절대 rb가 참조하는 대상이 b인 것이 아닙니다.
int a = 0 ;
const int &ra = a ;
int &rra = const_cast(ra) ;
컴파일러는 위 코드를 보고 다음과 같이 해석합니다.
1. 새로운 장소에 0을 넣고 여기에 이름 'a'를 붙인다.
2. 그 장소에 ra라는 이름을 또 붙이되 'ra'라는 이름을 사용한 수식에서는 그 장소의 값을 바꾸는 행위를 금지한다.
3. 마찬가지로 그 장소에 rra라는 이름을 붙이되 'rra' 라는 이름을 사용한 수식에서는 그 장소의 값을 바꾸는 행위를 허락한다.
a, ra, rra는 모두 한 장소를 가리킵니다.
다만 어떤 이름을 사용하느냐에 따라 장소에 들은 값을 바꾸는 행위를 허락하느냐 안 하느냐의 차이입니다.
rra = 10 ;
ra = 10 ;
두 다 같은 장소에 10이라는 값을 넣으려는 의도이나 컴파일러는 첫 번째만 허락하고 두 번째는 허락하지 않습니다.
댓글에 쓴 코드가 깨졌네요. 전부 원문에 있는 코드를
댓글에 쓴 코드가 깨졌네요. 전부 원문에 있는 코드를 인용한 것이니 이를 참조하시면 됩니다.
const는 변경자(Modifier)이고. constant는 상수 입니다.
용어가 좀 헛갈립니다. 저도 10년만에 오늘 처음 알았습니다.
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
일단. const_cast<>()를 찾아봤습니다.
일부 예제와 내용에 오류가 있을 수 있으니.
정확한 내용은 책을 보거나. 컴파일이 되는 개발도구로 값을 확인해 보시기 바랍니다.
0. 동적 변수를 사용한 경우 - 코드 예제1
const 변환자 int 형 데이터에 상수값이 바뀌었습니다.
1. 고정 변수를 사용한 경우 - 코드 예제2
C++ 에서 (int*) 명시적 형변환과 const_cast()에 결과는 같았습니다.
하지만. 결과적으로 const 변환자 int 형 데이터에 상수값 20은 바뀌지 않았습니다.
3. C 에서 const 변환자에 상수값은 명시적 형변환으로 바꿀 수 있었습니다.
4. C++ 에서 const 변환자에 상수값이 명시적 형변환으로 바뀌는것이 되는지는 모르겠습니다.
5. Visual C++ 컴파일러와 debug. gdb 등으로 어셈블리를 확인해보면.
보다 정확하게 알 수 있을것 같습니다. ㅡ_ㅡ;; 귀찮음...
6. C 에서의 T 는 배열을 의미했었습니다.
//http://codepad.org 에서 소스 코드를 컴파일하고. 확인해 보실 수 있습니다.
//-----------------------------------------------------------
//코드 예제1.
//메모리 할당을 통해서 적용된 경우.
#include
using namespace std;
//http://blog.naver.com/boomber13?Redirect=Log&logNo=80200032264
//http://en.wikipedia.org/wiki/Operator_delete
int main()
{
int i=0;
//변경자 데이터형 변수 int가 10개인 배열
const int* N = new int[10];
for(i=0; i<10; i++)
{
cout << *(N+i) << " ";
}
cout << endl;
//데이터형 변수인 int형 포인터
int* pN;
//
pN = (int*)(N);
pN = const_cast(N);
for(i=0; i<10; i++)
{
//error: assignment of read-only location 잘못 참조 되었을 경우 발생하는 메시지
// *(N+i) = i;
// cout << *(N+i) << " ";
*(pN+i) = i;
cout << *(pN+i) << " ";
}
cout << endl;
cout << N << '\t' << &N << '\t' << *N << endl;
cout << pN << '\t' << &pN << '\t' << *pN << endl;
delete [] N;
}
//-----------------------------------------------------------
//코드 예제2.
//고정 변수를 사용한 경우
//https://www.ics.com/designpatterns/book/staticcast.html
#include
using namespace std;
int main() {
const int N = 22;
int* pN;
pN = (int*)(&N);
pN = const_cast(&N);
cout << N << '\t' << &N << endl;
cout << *pN << '\t' << pN << '\t' << *(&pN) << '\t' << &(*pN) << '\t' << &pN << endl;
*pN = 33;
cout << N << '\t' << &N << endl;
cout << *pN << '\t' << pN << '\t' << *(&pN) << '\t' << &(*pN) << '\t' << &pN << endl;
}
//pN에 값인 *pN은 33으로 바뀌었지만.
//주소가 참조된 N의 값은 바뀌지 않았다.
//이것은 두값을 바꾸었지만. const 값은 바뀌지 않았슴을 이야기 한다.
//const int N = 20; 에서 const를 빼면. 둘다 33이 된다.
//-----------------------------------------------------------
//코드 예제3.
//고정 변수를 레퍼런스 참조한 경우
#include
using namespace std;
int main()
{
const int a = 10 ;
int &ra = const_cast(a) ;
cout << a << '\t' << &a << '\t' << endl;
cout << ra << '\t' << &ra << '\t' << endl;
ra = 20 ;
cout << a << '\t' << &a << '\t' << endl;
cout << ra << '\t' << &ra << '\t' << endl;
}
//코드 예제 2와 3의 결과가 같습니다.
//10 0xffe12778
//10 0xffe12778
//10 0xffe12778
//20 0xffe12778
//-----------------------------------------------------------
//코드 예제4.
//메모리 할당이 0인 경우. 해제를 하지 않으면 된다. ㅡ_ㅡ;;
#include
using namespace std;
int main()
{
const int * pa = new int[1];
int * pb = const_cast(pa);
cout << pa << '\t' << &pa << '\t' << *pa << endl;
cout << pb << '\t' << &pb << '\t' << *pb << endl;
*pb = 10;
cout << pa << '\t' << &pa << '\t' << *pa << endl;
cout << pb << '\t' << &pb << '\t' << *pb << endl;
//memory clobbered past end of allocated block
//0일경우. 메모리 해제시 오류 메시지
//new int[1]; 은 delete가 됨
// delete [] pa;
// delete pa;
}
각종 설명
When should static_cast, dynamic_cast, const_cast and reinterpret_cast be used?
http://stackoverflow.com/questions/332030/when-should-static-cast-dynamic-cast-const-cast-and-reinterpret-cast-be-used
기억부류 지정자(storage class specifier)
http://blog.naver.com/semi7623?Redirect=Log&logNo=100005635904
[Visual C++][강좌&팁] C++ 이야기 - [1] 캐스트 연산자 const_cast
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNo=20&no=7777&ref=7777
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
북마크합니다.
북마크합니다.
저는 이렇게 생각했습니다.
댓글 달기