본문 바로가기

프로그래밍/C++

[C++] new와 delete의 동적 할당

들어가며

이 시국이 계속 지속되는 한······.

당신의 새내기 생활 및 1학기 전부,
사이버 강의로 대체되었다.

아마 본인은 대학으로 상경하지 못한 체

현재 주거지에서 죽치고 있을 미래가 보인다.

이러고자 공부해서 대학 갔나

자괴감이 들고 괴롭다.


C언어를 공부하면서 malloc 함수와 free 함수의 필요성을

이해하는 것은 하나의 고비가 될 수 있다.

그러나 필자는 독자들이 힙 영역의 특성을 이해하고,

힙 메모리 할당 및 소멸에 필요한 함수가

malloc과 free 임을 알고 있다는 전제를 가지고

이번 글을 시작하도록 하겠다.

 

new & delete

우리가 기존에 듣도 보도 못 한, 그런 키워드를 배워볼 차례다.

일단 이해하기에 앞서, C의 동적 할당에는 2가지 불편한 점이 있다

그림 1 - 2가지 불편한 점

그런데 C++에서 제공하는 키워드 'new'와 'delete'를 사용하면

이러한 불편한 점들이 사라진다.

대충 'new'가 'malloc'을 대신하고,

'delete'가 'free'를 대신하는 키워드임을 추측할 수 있지 않은가?


아무튼 'new' 키워드의 문법은 다음과 같다.

  • 타입* 포인터 이름 = new 타입;

첫 번째의 타입(자료형)은 데이터에 맞는 포인터를 선언하기 위해,

두 번째의 타입은 메모리의 종류를 지정하기 이해 사용한다.

malloc 함수와 마찬가지로, 메모리 할당에 실패하면

'널 포인트'를 반환한다.

그리고 사용 방법을 정리하면 다음과 같다.

그림 2 - new 사용법

[그림 2]에서 보이듯이, new 연산자를 통해

할당받은 메모리는 따로 이름이 없다.

따라서 해당 포인터로만 그 메모리 공간에 접근할 수 있는 것이다.

또한 new 연산자 오른편에, 할당할 대상의 정보(타입)를

직접 명시하고 있음에 주목하길 바란다.


그리고 'delete' 키워드의 문법은 다음과 같다.

  • delete 포인터 이름;

사용법을 정리하면 다음과 같다.

그림 3 - delete 사용법

정리하면, new 연산 시 반환된 주솟값을 대상으로

delete 연산을 진행하되, 할당된 영역이 배열의 구조라면

'[]'를 추가로 명시해주기만 하면 된다.

 

그럼 적당히 코드로 끄적여 보도록 하자.

#include <iostream>

using namespace std;

int main()
{
    int* ptr_int = new int;
    *ptr_int = 100;

    double* ptr_double = new double;
    *ptr_double = 100.123;

    cout << "int형 숫자의 값은 " << *ptr_int << "입니다." << endl;
    cout << "int형 숫자의 메모리 주소는 " << ptr_int << endl;

    cout << "double형 숫자의 값을 " << *ptr_double << endl;
    cout << "double형 숫자의 메모리 주소는 " << ptr_double << endl;

    delete ptr_int;
    delete ptr_double;

    return 0;
}

 

또한, 일단 결론만 급발진해서 말하자면

new 함수와 malloc 함수의 동작 방식에는 차이가 있다.

이것과 관련하여서는

이후에 '클래스'와 '객체' 그리고 '생성자'에 대해서 알고 난 후

정확하게 이해할 수 있기 때문에

아무튼 지금은 어떤 차이가 있는지 안 알려줄 것이다.

히히.

 

힙에 할당된 변수를 포인터 없이 접근하기

'참조자의 선언'은 상수가 아닌 변수를 대상으로만

가능하다고 알고 있지 않은가? (const 참조자가 아닌 경우)

그렇다면 new 연산자를 이용해서 할당된 메모리 공간에도

참조자 선언이 가능할 것인가.

 

정의에 따르면, 변수의 자격을 갖추기 위해서는

메모리 공간이 할당되고, 그 공간을 의미하는 이름이 존재해야 한다.

하지만 C++에서는 new 연산자를 이용해서 할당된 메모리 공간

변수로 간주한다.

따라서 참조자의 선언이 가능하도록 하고 있다.

그래서 다음과 같은 코드도 가능하다.

int* ptr = new int;     // new 연산자로 동적 할당
int& ref = *ptr;        // 포인터 ptr에 참조자 ref 선언
ref = 20;               // 참조자 ref로 포인터 ptr에 접근하여 값 수정
cout << *ptr << endl;   // 출력

 

물론 코드를 굳이 저런 식으로 구성했다간

언제 어디서 누구에게 어떻게 욕먹을지 모르지만

우리는 참조자의 선언을 통해서

포인터 연산 없이 힙 영역에 접근했다는 것에

의의를 두어야 한다.

 

마치며

딱히 설명할 것들이 많지 않은 챕터였다.

메모리에 관한 것들도 본 블로그의 C 카테고리에서

설명했던 것들이니, 그다지 많이 설명할 것이 없다.

아무튼 아직 배워야 할 것들이 많이 남았다.

다음 글에서는 '클래스'를 다뤄볼 생각이다.


참고 및 출처

[2권분철] 윤성우의 열혈 C++ 프로그래밍
국내도서
저자 : 윤성우
출판 : 오렌지미디어 2010.05.12
상세보기