Computing

[C++] Pointers and References part 1

ysk1m 2025. 3. 25. 11:47

Variable과 Memory

어떤 variable이 선언될 때, variable을 위한 공간이 memory에 만들어지고 memory의 주소가 variable의 이름과 associate 된다.

변수명을 주소처럼 이용하는 것이다.

주소는 "&x"으로 접근할 수 있다.

Pointers

Pointer는 똑같은 변수이다...(어렵게 생각 no)

평범한 변수인데 단지 memory address가 value인 변수이다.

 

주로 8byte의 크기를 가진다.(integer:4byte, char:1byte)

 

pointer가 어떤 type의 data를 가지고 있느냐에 따라 pointer를 지정하는 방법이 다른데

type정보 *변수명=&x;
int *ptr=&x;

처럼 쓸 수 있다.

 

pointer 변수 ptr이 가리키는 주소에 담긴 value에 접근하는 방법을 dereference라고 한다.

*ptr;

 dereferencing(thecnical 변수이름은 아니지만 변수 이름처럼 사용할 수 있다.)

Dynamic memory allocation

runtime때 프로그램으로 하여금 메모리를 할당할 수 있게 하는 것이다.

 

cmalloc을 사용하여 얼마만큼 쓰고 싶은지 정해 heap 공간을 차지한다.

malloc 선언을 하고 메모리를 이용했으면 free를 써 끝낸다.

 

c++에서는 new라는 헤드를 가져와서 new와 delete을 통해 dynamic memory를 할당한다.

어떤 data type인지도 같이 적어야 한다.

int *array=new int[n]; //Array를 할당하는 경우
delete[] array;

int *ptr=new int; //Single object를 할당하는 경우
delete ptr;

 

memory leak를 막기 위해 꼭 delete []을 이용하여 마무리를 해야 한다.

예외처리 방법

  • 첫 번째 코드

예외가 발생할 가능성이 있는 코드를 try블록에 넣고, 실패할 경우 catch블록에 어떻게 할 것인지 작성한다.

할당 실패 시 발생하는 std::bad_alloc 클래스를 정의하고 e.what()을 이용하여 오류 메시지를 반환한다.

  • 두 번째 코드

예외를 발생시키지 않고, 실패하면 null pointer를 반환한다.

if를 이용하여 할당 실패 여부를 직접 확인한다.

에러 메시지를 standard error stream으로 출력한다.

Class pointer

Class(예를 들어 container의 vector 등)를 담고 있는 memory의 주소를 가리키는 pointer 변수이다.

vector를 heap에 동적 할당하면서 그 memory를 가리키는 myVector pointer를 지정한다.

따라서 vector의 element에 접근하기 위해서는 

(*myVector).member;
myVector->member;

이렇게 두 개로 쓸 수 있다.

Pointer Operations

Pointer를 지정할 때 type도 같이 정하는데 메모리 주소를 가리킨다는 점에서는 별로 중요하지 않은 부분이다.

하지만 dereferce 할 때 메모리 크기가 type마다 다르므로 pointer의 type이 중요하다.

예를 들어 intPtr+2인 경우는 8byte만큼 주소가 늘고 charPtr+2인 경우는 2byte만큼 주소가는다.

Multi-dimensional Dynamic array

int* ptr;은 int형 하나짜리 값의 주소를 저장하는 포인터다.

int** arr;은 int* 포인터들을 저장하는 포인터의 포인터이다.

int** arr=new int*[nRows];
for (int i=0; i <nRows;i++){
	arr[i]= new int[nCols];
    }

int**을 통해 arr 변수는 포인터를 저장하는 메모리의 주소를 담고있다.

여기에 int*[nRows]를 통해 nRows개만큼 pointer 변수가 생성된다.

이 문제를 풀어보면

  • arr+1:0x7f9da0f05e20+1*8= 0x7fc938705e28이된다. 여기서 8byte인 이유는 pointer의 pointer이기 때문이다.
  • *(arr+1): *(0x7fc938705e28)이므로0x7fc938705fd0이다.
  • *(arr+1)+2: *(arr+1)은 int type이기 때문에 0x7fc938705fd0+2*4=0x7fc938705fd8이 된다.
  • *(*(arr+1)+2): 5다.

arr가 들고 있는 주소를 갔을 때, 어떤 integer pointer 또는 어떤 memory 주소가 있을 거라고 가정 그렇기 때문에 1을 더한다는 건 8byte만큼 지난다는 것이다.

 

그 다음 가리킨 주소는 integer가 있다고 생각하면(맨 처음 본 게 integer pointer니깐) 두 번째 더할 때는 4byte가 지난다는 의미이다.

Static array

Static array의 이름은 pointer처럼 이용할 수 있다.(array의 첫 번째 element를 가리키는 pointer변수의 이름과 비슷한 역할을 한다.)

그냥 arr 이런 식으로(index를 안 쓰고 그냥 이름만 쓸 경우) 사용할 때를 말한다.

pointer처럼 사용할 수 있는 것이지 pointer처럼 주소를 따로 저장하는 것은 아니다.

포인터처럼 sizeof가 8byte가 아니라 배열 전체 크기이다.

 

pointer의 경우 pointer만 stack에 저장하고 heap에 데이터를 저장한다.

반면에 Static array는 stack에 직접 값들이 있다. 

cout<< arr << endl;
cout<< &arr << endl;
//서로 같은 값을 내보냄 두번째 &arr인 arr를 포인터처럼 생각하는게 아님