C++

C++ 포인터와 레퍼런스 정리

김구티2 2024. 4. 29. 19:25

1. 포인터와 레퍼런스

C++ 포인터와 레퍼런스는 모두 프로그램의 메모리, 메모리 주소 및 데이터를 처리하는 데 사용되는 메커니즘이다. 포인터는 다른 변수의 메모리 주소를 저장하는 데 사용되지만, 레퍼런스는 이미 존재하는 변수의 별칭(alias)을 만드는 데 사용된다.

C++의 포인터는 주소를 상징적으로 표현한 것이다. 이들은 프로그램이 레퍼런스에 의한 호출을 시뮬레이션하고, 동적 데이터 구조를 만들고 조작할 수 있도록 한다. 포인터는 변수의 주소나 메모리 위치를 저장한다.

구문:
datatype *var_name; 

 

예를 들어 int * ptr; 에서 ptr은 int 데이터를 유지하는 주소를 가리킨다.

 

예시 프로그램을 통해 포인터를 이해해 보도록 한다:

// C++ program to demonstrate use of pointers in C++;

#include <iostream>
using namespace std;

int main()
{
     int x = 10; // variable declared
     int* myptr; // pointer variable

     // storing address of x in pointer myptr
     myptr = &x;

     cout << "Value of x is: ";
     cout << x << endl;

     // print the address stored in myptr pointer variable
     cout << "Address stored in myptr is: ";
     cout << myptr << endl;

     // printing value of x using pointer myptr
     cout << "Value of x using *myptr is: ";
     cout << *myptr << endl;

     return 0;
}

 

출력:

Value of x is: 10
Address stored in myptr is: 0x7ffd2b32c7f4
Value of x using *myptr is: 10

 

위 프로그램은 값 10으로 초기화된 정수 변수 x와 포인터 변수 myptr을 선언한다. 그리고 x의 메모리 주소를 myptr에 할당한다. 그런 다음, x의 값과 myptr에 저장된 주소, 포인터 myptr을 역참조하여 얻은 x의 값을 출력한다.

2. C++에서의 포인터 적용

C++에서의 포인터 적용은 다음과 같다.

 

① 레퍼런스로 인수 전달: 레퍼런스로 전달하는 것은 두 가지 목적을 수행한다.
② 배열 요소 액세스: 컴파일러는 내부적으로 포인터를 사용하여 배열 요소에 액세스한다.
③ 여러 값을 반환하는 방법: 예를 들어, 숫자의 제곱근과 제곱근을 반환하는 방법 등이 이에 속한다.
④ 동적 메모리 할당: 포인터를 사용하여 메모리를 동적으로 할당할 수 있다. 동적으로 할당된 메모리의 장점은 명시적으로 삭제하기 전까지는 삭제되지 않는다는 것이다.
⑤ 데이터의 구조를 구현한다.
⑥ 메모리 주소가 유용한 시스템 수준 프로그래밍을 수행한다.

3. C++에서 포인터의 특징 및 사용

포인터는 몇 가지 중요한 기능을 가지고 있으며, 메모리 공간을 절약하고 메모리를 동적으로 할당하는 데 사용되고, 파일 처리 등에 사용된다. 포인터는 변수의 주소나 메모리 위치를 저장한다.


예시로, 포인터 ptr은 정수 변수의 주소를 유지하거나, ptr을 통해 값이 정수 값으로 액세스될 수 있는 메모리의 주소를 유지한다:

int *ptr;

4. this 포인터

this 포인터는 모든 비정적 멤버 함수 호출에 숨겨진 인수로 전달되며, 모든 비정적 함수의 본문 내에서 로컬 변수로 사용할 수 있다. 정적 멤버 함수에서 this 포인터는 객체 없이 정적 멤버 함수를 호출할 수 있으므로 사용할 수 없다. 각 함수에서 여러 객체에 의해 사용되는 멤버가 하나만 존재하더라도, 컴파일러는 함수의 이름과 함께 암시적 포인터를 this로 제공한다.

 

선언:

this->x = x; 

5. 레퍼런스

변수가 레퍼런스로 선언되면 기존 변수의 대체 이름이 된다. 선언문에 &를 넣어 변수를 레퍼런스로 선언할 수 있다. 함수에 C++ 인수를 전달하는 방법은 3가지가 있다.

 

① 값에 의한 호출 (call-by-value)
② 포인터 인수가 있는 레퍼런스에 의한 호출 (call-by-reference with a pointer argument)
③ 레퍼런스 인수가 있는 레퍼런스에 의한 호출 (call-by-reference with a reference argument)

 

레퍼런스의 예시:

// C++ Program to demonstrate use of references

#include <iostream>
using namespace std;

int main()
{
     int y = 10;

     // ref is a reference to x.
     int& myref = y;

     // changing value of y to 20
     y = 30;
     cout << "value of y is " << y << endl;
     cout << "value of myref after change in value of y is: "
             << myref << '\n';

     return 0;
}

 

출력:

value of y is 30
value of myref after change in value of y is: 30

 

위 프로그램은 레퍼런스의 사용을 보여준다. 먼저 정수 변수 y를 선언한 다음, y에 별칭인 레퍼런스 myref를 만든다. y의 값을 변경하면, y와 myref의 값을 모두 프린트한 후에 볼 수 있는 myref의 값도 변경된다.

6. 포인터 vs 레퍼런스

포인터와 레퍼런스는 모두 다른 함수 안에서 한 함수의 로컬 변수를 변경하는 데 사용될 수 있다. 또한 함수에 인수로 전달되거나 함수에서 반환될 때 큰 개체의 복사를 저장하여 효율성을 높일 수 있다.

이런 유사점이 있기는 하나, 포인터와 레퍼런스에는 분명한 차이도 존재한다.

 

① 레퍼런스는 포인터보다 약한 개념이다. 이는 아래의 내용을 읽다 보면 이해가 갈 것이다.
② 일단 레퍼런스가 생성되면, 나중에 다른 개체를 레퍼런스하도록 만들 수 없고, 다시 지정할 수 없다. 이것은 대신 포인터로 수행되는 경우가 많다.
③ 레퍼런스는 NULL일 수 없다. 그에 반해, 포인터는 유효한 것을 가리키고 있지 않음을 나타내기 위해 종종 NULL로 만들어기도 한다.
④ 선언할 때 레퍼런스를 초기화해야 한다. 그러나 포인터에는 이러한 제한이 없다.

 

* 포인터는 void로 선언할 수 있으나, 레퍼런스는 void로 선언할 수 없다. 예를 들어, 아래와 같다:

int a = 10;

void*aa = &a;. //it is valid

void &ar = a; // it is not valid

728x90

'C++' 카테고리의 다른 글

C++ 포인터 산술(Pointer Arithmetic)  (1) 2024.05.01
C++ 포인터(Pointers) 총정리  (0) 2024.04.29
C++ 람다식(Lambda expression) 총정리  (2) 2024.04.25
C++사용자 정의 예외  (0) 2024.04.25
C++ 스택 풀기(Stack Unwinding)  (0) 2024.04.24