이번 글에서 작성할 내용은 C++의 메모리 할당 연산자에 대해서 알아볼 것이다.
new, delete는 C++의 메모리 할당 연산자이며 각각 C의 malloc, free에 대응된다.
new의 기본 형식은 다음과 같다.
포인터 = new 타입[(초기값)];
// 예시
int* ptr = new int(4); // 4는 초기값이다.
delete ptr;
int* ptr = new int[4]; // 크기가 4인 배열을 할당한다.
delete[] ptr;
int* ptr{new int[5]}; // 크기가 5인 배열을 할당하는 또 다른 방법.
delete[] ptr;
int* ptr = new int[3]{}; // 0으로 초기화된 크기가 3인 배열을 할당한다.
delete[] ptr;
int* ptr{new int[5]{1, 2, 3, 4, 5}}; // 1, 2, 3, 4, 5로 각각의 원소가 초기화된 크기가 5인 배열 할당.
delete[] ptr;
int** ptr = new int[4][4]; // 컴파일 에러
int (*ptr)[5] = new int[10][5]; // ok
auto ptr = new int[10][5]; // ok
int** ptr = new int* [5];
for (int i = 0; i < 5; i++)
ptr[i] = new int[4];
for (int i = 0; i < 5; i++)
delete[] ptr[i];
delete[] ptr;
/////////////////////////////////////////////////////////////////////
class Point{
int x, y;
Point() : x(1), y(3)
{
std::cout << "Point 생성자 호출됨 \n";
}
Point(int _x, int _y) : x(_x), y(_y)
{
std::cout << "Point 생성자 호출됨 \n";
}
};
// 객체도 초기화가 가능함.
Point* ptr1 = new Test;
Point* ptr2 = new Test(10, 20);
delete ptr1;
delete ptr2;
위와 같은 케이스들을 보면 new로 할당하게 되었을 경우 반드시 delete로 메모리를 해제해야 한다. 그렇지 않은 경우 힙 메모리 공간에 할당한 메모리가 그대로 남아있게 되어 메모리 누수가 일어나게 된다.
이는 메모리 활용면이나 수많은 곳에서 오류를 나타낼 수 있기 때문에 delete로 반드시 메모리를 할당해서 그 부분을 가르키는 주소를 이용하여 해당 부분의 메모리를 해제시켜주어야 한다.
주의해야 할 점은 배열을 할당하였을 경우에는 delete[] ptr 이런식으로 해제해줘야 한다. 하나의 변수를 지우듯이 delete를 사용하게 되면 배열의 첫번째 요소만 해제되고 나머지는 해제가 되지 않기 때문이다.
그리고 new는 할당과 동시에 초기화가 가능한데 위의 예시들로 그 방법을 확인할 수 있다.
new는 C의 malloc과는 다르게 std::bad_alloc이라는 예외를 발생시킨다. 즉, 반환 값을 주는 것이 아니라고 보는게 더 정확하다고 할 수 있다.
이를 확인하는 방법은 다음과 같다.
#include <iostream>
int main(void)
{
try
{
int* ptr = new int[3];
}
catch (std::bad_alloc & e)
{
std::cerr << "bad_alloc이 발생했다: " << e.what() << '\n';
}
return 0;
}
물론 예외를 발생시키지 않게 하는 방법도 있다.
int* ptr = new(std::nothrow) int[4];
if (ptr == nullptr)
std::cerr << "동적할당 실패" << std::endl;
new와 delete의 가장 큰 장점은 객체가 생성 및 파괴될 때 생성자와 파괴자가 호출된다는 점이다. 이 점만 제외하면 malloc과 free와 그렇게 차이는 나지 않는다.
OOP란? (0) | 2023.08.03 |
---|---|
C++에서의 구조체 (0) | 2023.08.03 |
C++의 새로운 입출력 - cout, endl, cin (0) | 2023.06.10 |
using 키워드 (0) | 2023.06.10 |
namespace - 이름공간 (0) | 2023.06.10 |