관리 메뉴

Kim's Programming

C++ 에서의 동적 할당 new/delete 본문

Programming/Cplusplus

C++ 에서의 동적 할당 new/delete

Programmer. 2015. 8. 27. 01:24

new, delete는 C의 malloc, free에 대응되는 C++의 메모리 할당 연산자이며 실행중 메모리를 할당한다는 점에서 용도가 비슷합니다.


포인터 = new 타입[(초기값)];


new 다음에 할당 대상 타입을 밝히면 sizeof(타입)만큼의 메모리가 할당되고 할당된 포인터가 리턴됩니다. new가 리턴하는 번지는 같은 타입의 포인터 변수로 대입받습니다. 할당과 동시에 메모리를 초기화하고 싶으면 타입 다음의 괄호에 원하는 초기값을 적되 초기화를 할 필요가 없으면 생략할 수 있습니다. 초기화하지 않은 메모리는 물론 쓰레기값을 가집니다. 메모리 부족등의 이유로 할당에 실패하면 NULL을 리턴하는데 원치적으로 이 리턴값을 점검해 보아야 하지만 32비트 환경에서는 실패할 확률이 거의 없어 점검을 생략하는 경우도 많습니다. 이렇게 할당된 메모리를 해제할 떄는 delete 연산자를 사용하는데 해제할 포인터를 delete 다음에 지정합니다. 만약 할당만 하고 해제를 하지 않으면 메모리 일부를 사용할 수 없게 되는 메모리 누수(Memory Leak)가 발생하므로 동적 할당한 메모리는 반드시 delete해야합니다. 한 포인터에 대해 delete를 두번 하는 것은 안되지만 NULL 포인터를 삭제하는 것은 가능합니다. 즉 다음과 같이 할 필요는 없습니다.


1
2
3
4
if(pi != NULL)
{
    delete pi;
}
cs

delete는 NULL 포인터에 대해서는 아무런 동작도 하지 않도록 정의되어 있으므로 안전합니다. 위 코드에서 if문으로 점검할 필요없이 무조건 pi를 해제해도 상관없습니다. 다음은 new, delete로 정수형 변수 하나를 동적으로 생성해 본 것입니다.

1
2
3
4
5
6
7
8
9
#include<iostream>
 
void main()
{
    int *pi = new int;
    *pi = 123;
    printf("*pi=%d\n"*pi);
    delete pi;
}
cs

new연산자에 의해 정수형 하나를 저장할 만큼의 공간(4바이트)이 할당되는데 할당된 포인터를 정수형 포인터 변수 pi로 대입받았습니다. 힙에 할당된 4바이트를 pi가 가리키고 있으며 이후 *pi는 동적 할당된 정수형 변수가 되며 정수값 하나를 기억할 수 있습니다. 위 소스에서는 *pi에 123이라는 정수값을 대입하고 확인을 위해 출력만 해 보았습니다. 다 사용하고 난 다음에는 delete pi로 해제합니다. 다음은 new 연산자로 실수형과 문자형 변수를 할당하는 경우입니다.

1
2
double *pd = new double;
char *pc = new char;
cs


pd에는 8바이트가 할당되고 pc에는 1바이트가 할당 될 것입니다. 잘 사용되지는 않지만 new int;라고 쓰는 대신 괄호를 써서 new(int)라고 쓰는 방법도 있으며 이떄도 new(int)(123)형식으로 초기값을 지정 할 수도 있습니다. new/delete 연산자는 malloc/free와 기능적으로 동일하기 때문에 다음과 같이 써도 동일하게 동장합니다.

1
2
3
4
int *pi = (int *)malloc(sizeof(int));
*pi = 123;
printf("*pi=%d\n",*pi;)
free(pi);
cs

new 대신 malloc을 사용했고 delete 대신 free를 사용했습니다. 메모리 할당의 면에서만 본다면 new/delete는 malloc/free와 동일하지만 차이점도 많이 있습니다. new/delete는 malloc/free보다 메모리를 관리하는 방식이 훨씬 더 진보적이며 속도도 빠르고 OOP에 적합한 특징들을 많이 가지고 있습니다. 어떤 점이 다른지 알아보겠습니다.


    • malloc/free는 라이브러리가 제공하는 함수인데 비해 new/delete는 언어가 제공하는 연산자입니다. 그래서 별도의 헤더 파일을 포함할 필요없이 언제든지 사용할 수 있으며 이 연산자를 쓴다고 해서 프로그램이 커지는 것도 아닙니다. 연산자이기 떄문에 사용자 정의 타입에 대해 오버로딩할 수도 있습니다.

    • malloc 함수는 필요한 메모리양을 바이트 단위로 지정하고 void * 를 리턴하므로 sizeof 연산자와 캐스트 연산자의 도움을 받아야 합니다. 이에 비해 new는 할당한 타입을 지정하고 해당 타입의 포인터를 리턴하므로 sizeof연산자와 캐스트 연산자를 쓸 필요가 없습니다. 할당한 타입과 같은 타입의 포인터 변수로 대입만 받으면 됩니다.

    • malloc은 메모리를 할당하는 것만이 목적이므로 초기값을 줄 수 없지만 new연산자는 동적으로 생성한 변수의 초기값을 지정할 수 있습니다. 즉 할당과 동시에 초기화를 할 수 있는데 할당 타입 다음의 괄호에 초기값을 적어주면 됩니다. int *pi = new int, *pi=123; 두 문장은 int *pi = new int(123); 하나로 합칠 수 있습니다.

    • new 연산자로 객체를 할당할 때 생성자가 자동으로 호출됩니다. 생성자란 객체를 자동으로 초기화하는 특별한 함수입니다. 생성자는 생성과 동시에 개게를 초기화할 수 있도록 함으로써 클래스가 기존 타입과 동등한 자격을 가지도록 하는 중요한 역할을 합니다. 생성자를 호출한다는 점이 malloc과 new의 가장 큰 차이점이고 C++에서 별도의 할당 연산자가 추가된 이유입니다. 마찬가지로 delete로 객체를 삭제할떄는 파괴자라는 특별한 함수가 자동으로 호출됩니다.

malloc/free를 사용할 수도 있고 객체를 할당할 때는 반드시!! new/delete를 써야합니다. 단, 할당, 해제 함수는 반드시 짝을 맞추어야 하며 섞어서 쓸 수 없습니다. malloc으로 할당하면 free로 해제하고 new로 할당했으면 delete로 해제해야합니다.



'Programming > Cplusplus' 카테고리의 다른 글

C++ - 클래스(Class)(2/2)  (0) 2015.08.28
C++ - 클래스(Class)(1/2)  (0) 2015.08.28
C++ - 구조체의 확장  (0) 2015.08.27
C++ 입력함수 cin을 사용해보자  (0) 2015.07.24
C++에서의 Hello World!를 구현해보자!  (0) 2015.07.24