[02-5] malloc & free를 대신하는 new&delete

김민성·2022년 7월 11일
post-thumbnail

new & delete

길이정보를 인자로 받아서, 해당 길이의 문자열 저장이 가능한 배열을 생성하고, 그 배열의 주소 값을 반환하는 함수를 정의해보자.

MemMalFree.cpp

#include <iostream>
#include <string.h>
#include <stdlib.h>
using namespace std;

char * MakeStrAdr(int len) {
    char * str = (char*)malloc(sizeof(char)*len);
    return str;
}

int main(void) {
    char *str = MakeStrAdr(20);
    strcpy(str, "I am so happy!");
    cout<<str<<endl;
    free(str);
    return 0;
}
I am so happy!

위의 코드를 살펴보면,

char * str = (char*)malloc(sizeof(char)*len);

문자열 저장을 위한 배열을 힙 영역에 할당하고 있다.

free(str);

힙에 할당된 메모리 공간을 소멸한다.

위 예제는 C언어에서의 동적할당을 보이기 위한 것이다. 그런데 이 방법에는 다음의 두 가지 불편함이 따른다.

  • 할당할 대상의 정보를 무조건 바이트 크기단위로 전달해야 한다.
  • 반환형이 void형 포인터이기 떄문에 적절한 형 변환을 거쳐야 한다.

그런데 C++에서 제공하는 키워드 new와 delete를 사용하면 이러한 불편한 점이 사라진다. new는 malloc 함수를 대신하는 키워드이고, delete는 free 함수를 대신하는 키워드이다. 먼저 키워드 new의 사용방법을 정리하면 다음과 같다.

  • int형 변수의 할당
    int * ptr = new int;

  • double형 변수의 할당
    double * ptr2 = new double;

  • 길이가 3인 int형 배열의 할당
    int * arr1 = new int[3];

  • 길이가 7인 double형 배열의 할당
    double * arr2 = new double[7]

다음은 delete의 사용법이다.

  • int형 변수의 소멸
    delete ptr;

  • double형 변수의 소멸
    delete ptr2;

  • 길이가 3인 int형 배열의 소멸
    delete []arr1;

  • 길이가 7인 double형 배열의 소멸
    delete []arr2;

앞서 보인 예제 MemMalFree.cpp를 변경해 new와 delete의 사용 예를 보자.

NewDelete.cpp

#include <iostream>
#include <string.h>
using namespace std;

char * MakeStrAdr(int len) {
    //char * str = (char*)malloc(sizeof(char)*len);
    char * str = new char[len];
    return str;
}

int main(void) {
    char *str = MakeStrAdr(20);
    strcpy(str, "I am so happy!");
    cout<<str<<endl;
    //free(str);
    delete []str;
    return 0;
}
I am so happy!

객체의 생성에는 반드시 new & delete

malloc & free 함수 호출의 문제점을 다음 예제를 통해 알아보자.

NewObject.cpp

#include <iostream>
#include <stdlib.h>
using namespace std;

class Simple {
public:
    Simple() {
        cout<<"I'm simple constructor!"<<endl;
    }
};

int main(void) {
    cout<<"case 1: ";
    Simple * sp1=new Simple;

    cout<<"case 2: ";
    Simple * sp2= (Simple*)malloc(sizeof(Simple)*1);

    cout<<endl<<"end of main"<<endl;
    delete sp1;
    free(sp2);
    return 0;
}
case 1: I'm simple constructor!
case 2: 
end of main

코드를 파악해보자.

class Simple {
public:
    Simple() {
        cout<<"I'm simple constructor!"<<endl;
    }
};

클래스인데 천천히 알아가자.. C언어의 구조체라고 생각하고 있자.

Simple * sp1=new Simple;

클래스에 정의되어 있는 자료형(Simple)을 근거로, new 연산자를 이용해 힙 영역에 변수를 할당하고 있다.

Simple * sp2= (Simple*)malloc(sizeof(Simple)*1);

클래스에 정의되어 있는 자료형(Simple)을 근거로, malloc 함수호출을 통해 힙 영역에 변수를 할당하고 있다.

실행결과를 보면, case1은 출력되었으나, case2는 출력되지 않은 것을 볼 수 있다.
여기서 new와 malloc 함수는 '메모리 할당'이라는 측면에서는 비슷할 수 있으나, 동적방식에는 차이가 있다는 것을 알 수 있다.

이후에 클래스와 객체, 그리고 생성자에 대해 알고 나면, 차이를 정확이 무엇인지 알 수 있을 것이다.

힙에 할당된 변수? 이제 포인터를 사용하지 않아도 접근할 수 있어요.

참조자의 선언은 상수가 아닌 변수를 대상으로만 가능하다(const 참조자가 아닌 경우). 그렇다면 new 연산자를 이용해 할당된 메모리 공간에도 참조자의 선언이 가능할까?
가능하다. C++에서는 new 연산자를 이용해 할당된 메모리 공간도 변수로 간주해 참조자의 선언이 가능하다.

int *ptr = new int;  
// 힙 영역에 할당된 변수에 대한 참조자 선언
int &ref = *ptr;
ref = 20;
cout<<*ptr<<endl;	// 출력결과는 20!

변수의 성향을 지니는 (값의 변경이 가능한) 대상에 대해서는 참조자의 선언이 가능하다!

profile
다양한 활동을 통해 인사이트를 얻는 것을 즐깁니다. 저 또한 인사이트를 주는 사람이 되고자 합니다.

0개의 댓글