가끔 C/C++ 프로그래밍을 하다 보면 더블 포인터 인자를 가진 API 함수를 보곤 한다.
굳이 더블 포인터를 사용하는 까닭이 뭘까?
#include <iostream>
void Swap(int* _A, int* _B)
{
int C = 0;
//스왑
C = *_A;
*_A = *_B;
*_B = C;
}
int main()
{
int* APtr = new int(3);
int* BPtr = new int(5);
std::cout << *APtr << std::endl;
std::cout << *BPtr << std::endl << std::endl;
Swap(APtr, BPtr);
std::cout << *APtr << std::endl;
std::cout << *BPtr << std::endl;
delete APtr;
delete BPtr;
return 0;
}
위 코드는 포인터 변수가 가진 값을 스왑해주는 코드이다.
포인터가 가진 변수의 값을 바꾸기 위한 목적이라면 위 코드로도 충분하지만
만약 포인터 자체의 값, 즉 주소값을 바꾸고 싶다면 어떻게 해야 할까?
#include <iostream>
void Swap(int** _A, int** _B)
{
int* C = nullptr;
C = *_A;
*_A = *_B;
*_B = C;
}
int main()
{
int* APtr = new int(3);
int* BPtr = new int(5);
std::cout << APtr << std::endl;
std::cout << BPtr << std::endl;
Swap(&APtr, &BPtr);
std::cout << APtr << std::endl;
std::cout << BPtr << std::endl;
delete APtr;
delete BPtr;
return 0;
}
그러면 위와 같이 더블 포인터를 사용해야만 한다.
그냥 포인터만으로는 해결할 수 없는 문제인 건가?
깊게 생각해보면 해결할 수 없는 게 당연하다.
//원본은 바뀌지 않음
void Swap(int* _A, int* _B)
{
int* C = nullptr;
C = _A;
_A = _B;
_B = C;
}
Swap() 함수 속 매개변수는 스택 영역에 할당될 지역변수이다.
포인터 변수 _A와 _B는 힙의 메모리 주소를 복사받은 또 하나의 지역변수이기 때문에
그 둘의 값을 바꿔도 원본(main() 속 APtr, BPtr)에는 반영될 수 없다.
그렇다면 원본에 반영되기 위해선 어떻게 해야 할까?
우선 일반 변수와 똑같이 포인터를 가르키는 포인터 변수를 만들어야 한다.
사실상 매개변수로 일반 변수를 받는 함수와 포인터로 받는 함수는 본질적으로 다른 부분이 없다.
변수의 값을 바꾸기 위해 해당 변수의 주소값을 들고 있는 포인터를 매개변수로 두는 것이고
포인터의 값을 바꾸기 위해 해당 포인터의 주소값을 들고 있는 더블 포인터를 매개변수로 두는 것.
따라서 더블 포인터를 매개변수로 받는 함수에 포인터를 넣어주면
포인터가 가르키던 메모리(주소값)가 달라져서 나온다는 것 또한 예상할 수 있다.
'둥지 > CS' 카테고리의 다른 글
C# 인터페이스와 추상 클래스 정리 (0) | 2023.07.21 |
---|---|
[C++ 키워드] const, constexpr (0) | 2023.06.22 |
캐싱 (0) | 2023.04.03 |