공부/C++ \C#

레퍼런스와 포인터의 차이

Lero God 2018. 5. 15. 14:51

1. 포인터는 재할당 할 수 있습니다.


1
2
3
4
5
6
7
8
int x = 5;
int y = 6;
int* p;
= &x;
= &y;
*= 10;
assert(x == 5);
assert(y == 10);



레퍼런스는 무조건 초기화 할 때 할당 해줘야 합니다.

1
2
3
int x = 5;
int y = 6;
int& r = x;



2. 포인터는 스택에 자신 고유의 주소를 가지고 있지만 (x86 운영체제에서 4 바이트), 반면 레퍼런스는 원본 변수와 같은 메모리 주소를 공유하면서 스택 공간에 자리를 차지합니다. 레퍼런스가 원본 변수랑 같은 주소를 공유하니깐 그냥 레퍼런스를 원본의 또 다른 이름이라고 생각하면 됩니다. 참고로 포인터가 가르키는 것은 스택뿐만 아니라 힙에 있을 수 있습니다. 레퍼런스도 마찬가지입니다. 여기서 내가 말하고자 한건 포인터는 무조건 스택을 가르킬 필요는 없다는 것입니다. 포인터는 단지 메모리는 주소를 담는 변수일 뿐입니다. 이 변수는 스택에 있습니다. 레퍼런스는 스택에 자신만의 공간이 있고 주소는 참조하는 변수랑 같습니다.
 이건 컴파일러가 알려주지 않는 레퍼런스의 진짜 주소가 있다는걸 알려줍니다.

1
2
3
4
5
int x = 0;
int& = x;
int* p = &x;
int* p2 = &r;
assert(p == p2);



3. 포인터의 포인터의 포인터처럼 여러번 참조하는 방식을 쓸 수 있는 반면에 레퍼런스는 한 번만 참조 할수있습니다.

1
2
3
4
5
6
7
8
9
int x = 0;
int y = 0;
int* p = &x;
int* q = &y;
int** pp = &p;
pp = &q; //*pp = q;
**pp = 4;
assert(y == 4);
assert(x == 0); 



4. 포인터에는 직접적으로 nullptr을 할당할 수 있는데 레퍼런스는 그렇게 못합니다. 하지만 특정한 방법으로 레퍼런스의 주소를 nullptr로 만들수 있긴 합니다.


1
2
3
int* p = nullptr;
int& r = nullptr; //컴파일 에러
int& r = *p; //컴파일 잘된당, 특히 nullptr가 함수 호출 뒤에 감춰져 있을때. 주소 0을 갖고 있고 존재하지 않는 int를 참조하게 된다. 
cs


5. 포인터는 배열을 iterate 할 수 있습니다. ++ 연산을 이용해서 포인터가 가르키는 곳의 다음 곳을 가르킬 수 있고, +4 를 이용하면 5번째 원소를 가르킬 수 있다. 가르키는 객체의 크기에 상관 없이 할 수 있습니다.


6. 레퍼런스는 다른 작업 없이 바로 쓸 수 있는데 포인터는 * 로  가르키는 메모리 공간에 접근 할 수 있습니다.


7. 포인터는 메모리 주소를 담는 변수입니다. 레퍼런스는 어떻게 선언되었든, 참조하고 있는 객체와 같은 메모를 주소를 갖습니다.


8. 레퍼런스는 배열에 넣을 수 없지만 포인터는 넣을 수 있습니다.


9. const 레퍼런스는 임시 변수를 참조 할 수 있습니다. 포인터는 그럴 수 없습니다.


1
2
const int& x = int(12); // 오케이
int* y = &int(12); // 에러



const&를 argument list에서 더 안전한게 쓸 수 있습니다.




원본 : https://stackoverflow.com/questions/57483/what-are-the-differences-between-a-pointer-variable-and-a-reference-variable-in

'공부 > C++ \C#' 카테고리의 다른 글

C++ 프로그래밍 : 런타임 타입 정보(Runtime Type Information)  (0) 2020.06.03
인라인 (Inline)  (0) 2018.08.08
vector의 size와 capacity  (0) 2018.07.04
사용되지 않음 #pragma deprecated  (0) 2018.05.11
volatile 키워드  (0) 2018.05.11