1. 포인터는 자신이 가리키는 주소 값을 언제든 변경할 수 있고 레퍼런스는 초기화할 때 반드시 값을 할당해줘야 한다.
int main()
{
int number_1 = 10;
int number_2 = 20;
// 주소 값 변경이 가능하다.
int* pI = &number_1;
pI = &number_2;
int &refI; // 에러 : 참조(레퍼런스) 변수는 초기화가 필요하다.
int &refI = number_1;
refI = number_2; // number_1의 참조가 되는것이 아닌, number_2의 값이 들어간다.
return 0;
}
2. 포인터는 운영체제에 따라 4, 8바이트 메모리 크기, 레퍼런스는 자신이 참조하는 메모리의 크기를 가지게 된다.
class TestClass
{
public:
int m_iData;
int m_iArrData[5];
public:
void RefCallFunction(const TestClass& _ref)
{
size_t size = sizeof(_ref);
cout << "size : " << size << endl;
}
void PointerCallFunction(const TestClass* _ptr)
{
size_t size = sizeof(_ptr);
cout << "size : " << size << endl;
}
};
int main()
{
TestClass cls = TestClass();
cls.RefCallFunction(cls);
cls.PointerCallFunction(&cls);
return 0;
}
결과
size: 24 (TestClass 크기) - RefCallFunction()
size : 4 (x86 4바이트) - PointerCallFunction()
3. 포인터는 nullptr로 할당(초기화)할 수 있지만 레퍼런스는 nullptr로 할당할 수 없다.
int* p = nullptr;
int& ref = nullptr; // 에러 : 비const 참조에 대한 초기 값은 lvalue여야 한다.
int a = 3;
int b = 4;
int& ref2 = a + b; // 에러 : 비const 참조에 대한 초기 값은 lvalue여야 한다.
const int& ref3 = a + b; // 컴파일 가능
rvalue? 우측값은 대입 시에 오직 오른쪽에만 오는 식. 상수(const)라고 볼 수 있다.
레퍼런스 형태로 rvalue 타입의 값을 담기 위해서는 상수에 대한 참조자 형식을 사용해야 한다.
4. 포인터는 배열 형식으로 접근할 수 있으며, 포인터에 + 연산을 이용하여 다음 메모리로 접근할 수 있다.
int arr[5] = { 0, 1, 2, 3, 4 };
int* pArr = arr;
// 주소 값
cout << "arr[0] Adress : " << pArr << endl;
cout << "arr[3] Adress : " << pArr + 3 << endl;
// * 키워드를 이용한 역참조
cout << "arr[0] value : " << *pArr << endl;
cout << "arr[3] value : " << *(pArr + 3) << endl;
5. 포인터는 메모리 주소를 담는 변수, 레퍼런스는 자신이 참조하는 메모리의 주소로 된다.
6. 레퍼런스의 배열과 배열의 레퍼런스 차이
- 레퍼런스의 배열
int a, b;
int& arr[2] = { a, b } ;
구글링! 결과 C++ 규정에서는 There shall be no references to references,no arrays of references, and no pointers to references (레퍼런스의 레퍼런스,레퍼런스의 배열, 레퍼런스의 포인터는 존재할 수 없다.)
왜? 5번에서 레퍼런스는 자신이 참조하는 메모리의 주소로 대체된다고 했는데, 위 코드의 arr은 배열의 시작주소가 된다.
메모리의 주소를 담기 위해서는 포인터 자료형이 필요하다. 레퍼런스 형태의 배열은 모순이된다.
- 배열의 레퍼런스
int a, b, c;
int arr[3] = { a, b, c};
int(&ref)[3] = arr;
// 포인터로 사용하는 경우
int *pArray = arr;
&ref는 array[0], [1], [2] 값을 ref[0], ref[1], ref[2]로 참조할 수 있다. 하지만 이렇게 사용하는 경우는 거의 없다.
이유로는 배열의 크기가 같아야하며, 위 코드는 포인터로 사용할 경우 더 쉽고 편하게 사용할 수 있기 때문이다.
'C++' 카테고리의 다른 글
얕은 복사(Shallow Copy) 깊은 복사(Deep Copy) (0) | 2019.07.12 |
---|---|
복사 생성자(Copy Constructor) (0) | 2019.07.11 |
다중 상속(Diamond of Death)의 문제점 (0) | 2019.07.10 |
상속을 사용하는 의미 (0) | 2019.07.09 |
순수 가상 함수(Pure Virtual Function) (0) | 2019.07.09 |