출처: http://elky.tistory.com/209
포인터(*)란 아시다시피, 메모리 주소를 가리키는 변수입니다.
가리키는 곳은 언제든 변할 수 있고, 아무곳도 가리키지 않는 상태(NULL 포인터)도 있습니다.
참조자(&)란 뭘까요? 참조자는 변수의 다른 이름입니다.포인터와 비슷하죠?
포인터와의 차이점은 참조자는 아무것도 가리키지 않는 상태가 없다는 것입니다.
포인터가 어려운 이유는 사용법 자체가 아니라 관리가 어렵기 때문입니다.
다음 코드를 살펴 보시죠. 포인터로 인해 발생할 수 있는 몇가지 상황을 보여줍니다.
int *piDynamic = newint; 됐기에 주인 잃은 포인터가 됨. if(piPtr) 한번 delete 된 곳을 또 delete 했기에 문제 발생. |
1. 주인 잃은 포인터
가리키고 있는 객체는 사라졌지만, 그 객체를 가리키고 있던 포인터 변수의 값은 NULL로 지정되지 않아
생기는 문제
2. NULL 포인터 참조
NULL 포인터일 경우는 아무것도 가리키지 않는 상태이기에 참조하면 안되는데, 참조를 시도하는 것
3. 포인터 delete 두번
delete할 때 NULL 포인터로 만들지 않아, 유효한 포인터로 판단해 또 다시 delete를 시도하는 문제
이 처럼 포인터 사용시에는 늘 주의깊게 신경써야만 합니다.
포인터로 인해 발생하는 문제들은 대부분 끔찍한 결과를 낳기 때문입니다.
그렇다면...C++에서 야심차게 도입한 참조자에는 이런 문제가 없을까요?
그렇진 않았습니다.
참조자 역시 포인터와 마찬가지로 자신이 가리키던 객체보다, 참조자가 수명이 길면 안됩니다.
아래 코드를 보시면, 참조자의 실체를 파악하실 수 있을 겁니다.
std::queue<int> qTest; qTest.push(1); // queue는 push시에 내부적으로 동적 할당 함 int & nTest = qTest.front(); // 동적 할당된 1이 저장된 장소의 참조자를 리턴 qTest.pop(); // pop시에는 동적할당을 해제함. 현재 nTest는 1이 저장되었었지만 지금은 해제된 주소를 가리킴.
qTest.push(2); // 싱글 스레드이기에, 1이 저장되어있었던 주소를 동적 할당받아서 2를 대입. printf("%d\n", nTest); // nTest는 실제로는 포인터이기에 1이 저장되었던 주소를 참조해 2를 출력함 |
어떤가요? 참조자도 가리키는 대상이 사라진다면 (현재의 예는 동적할당되는 객체였지만,임시 변수도 마찬가지), 주인 잃은 참조자가 될 수 있습니다.
그렇지만 참조자는 위 문제만 주의한다면, 포인터처럼 NULL검사를 할 필요가 없습니다.
그리고 포인터처럼 니모닉 (별칭) 기능을 충실히 해주죠.
참조자를 사용할 수 있는 상황이라고 판단이 되면, 포인터보다 참조자를 사용하는 것이 좋습니다.
정리하자면, 참조자는 변수의 별칭이기에 특정 변수의 다른 이름처럼 사용 가능합니다.
NULL (아무것도 가리키지 않는) 상태가 없다면 참조자를, NULL 상태가 있거나 동적할당된 데이터를 관리하려면 포인터를 써야합니다.
또한, 포인터나 참조자 모두 자신이 가리키는 대상이 사라질 때를 주의해야 한다는 점에 늘 유념해서 코딩 하셔야 합니다.
-------------------------------------------------------------------------------------------------
[포인터와 참조의 문법적 비교]
1. 포인터 변수는 주소를 가지고 언제든지 주소를 다시 바꿀 수가 있습니다.
int b , c;
int *a;
a = &b;
a = &c;
참조 변수는 초기화 할 때 설정한 변수의 주소를 이후에 변경할 수 없습니다.
int b , c ;
int &a =b;
a = c ; // 변경 할 수 없다.
2. 위 예제처럼 포인터 변수는 &를 나타내서 주소를 설정하는데 반해, 참조 변수는 b 와 같이
변수명을 그대로 사용해서 주소를 설정한다.
3. 포인터는 *a 형태에서만 값을 조작할 수 있지만, 참조는 변수명만으로도 직접 값을
조작할 수 있다.
4. 포인터는 주소와 값을 조작 할 수 있지만, 참조는 값만을 조작 할 수 있다.
참조 변수에 주소를 설정하는 것은 초기화 때만 할 수 있기 때문이다. ( 참조 변경 X )
5. 참조에 포인터를 할당 할 수 없다.
6. 참조는 오프셋 값을 더하는것과 같은 수치 연산을 할 수 없다.
'IT_Programming > C · C++' 카테고리의 다른 글
[C] 동적 메모리 할당으로 다이아몬드 찍기 (0) | 2009.05.27 |
---|---|
[C++] 연산자 오버로딩 정리와 예제... (0) | 2009.05.16 |
[펌] 최적화 코딩 방법 (0) | 2008.12.18 |
printf("[%s][%s][%d]\n",_FILE_,_FUNTION,_LINE_);을 이용한 디버깅 (0) | 2008.02.10 |
offsetof() : 중첩된! 클래스에서 중첩한! 클래스의 포인터 얻기. (0) | 2008.01.10 |