이번 글에서는 C++의 배치 new(Placement New) 연산자에 대해 알아보겠습니다. 배치 new는 일반적인 new 연산자의 변형된 형태입니다.
일반 new와 배치 new의 차이점
먼저 일반적인 new 연산자가 수행하는 두 가지 작업을 살펴봅시다.
- 메모리 할당: 힙(heap) 영역에 필요한 메모리를 확보합니다.
- 객체 생성: 할당된 메모리 공간에 객체를 생성(construct)합니다.
반면 배치 new는 메모리를 새로 할당하지 않고, 개발자가 지정한 주소에 직접 객체를 생성합니다.
메모리 해제 관련 주의사항
일반 new로 할당한 메모리는 delete 키워드로 해제할 수 있습니다. 하지만 배치 new에는 이에 대응하는 '배치 delete' 기능이 존재하지 않습니다. 따라서 배치 new로 생성한 객체를 소멸시킬 때는 명시적으로 소멸자(destructor)를 호출해야 하며, 실제 메모리 자체는 원래 할당 방식에 맞게 별도로 해제해야 합니다.
배치 new의 장점
핵심을 요약하면, 배치 new는 이미 할당되어 있는 메모리 위에 객체를 '생성'할 수 있게 해주는 기능입니다. 이미 확보된 메모리를 재활용하기 때문에 새로운 메모리를 다시 할당하는 과정이 생략되어 성능 최적화에 유용합니다. 게임 엔진, 임베디드 시스템, 커스텀 메모리 풀(memory pool) 구현 등에서 널리 활용됩니다.
기본 문법
new (address) (type) initializer
괄호 안에 객체를 생성하고자 하는 주소를 지정하면, 해당 타입의 객체가 그 주소에 생성됩니다. 아래 예제 코드를 통해 확인해 보겠습니다.
예제 코드
#include<iostream>
using namespace std;
int main() {
int a = 5;
cout << "a = " << a << endl;
cout << "&a = " << &a << endl;
// 배치 new를 사용하여 변수 a의 값을 100으로 변경
int *m = new (&a) int(10);
cout << "\nAfter using placement new:" << endl;
cout << "a = " << a << endl;
cout << "m = " << m << endl;
cout << "&a = " << &a << endl;
return 0;
}실행 결과
a = 5 &a = 0x22fe34 After using placement new: a = 10 m = 0x22fe34 &a = 0x22fe34
결과 분석
실행 결과를 보면 변수 a의 주소(&a)와 포인터 m이 가리키는 주소가 동일한 것을 확인할 수 있습니다. 즉, 배치 new는 새로운 메모리를 할당하지 않고 기존 변수 a가 차지하고 있는 메모리 공간에 새로운 정수 값(10)을 직접 생성한 것입니다. 그 결과 a의 값이 5에서 10으로 변경되었습니다.
이처럼 배치 new는 특정 메모리 위치에 객체를 직접 구성할 수 있게 해주는 강력한 도구이며, 메모리 재할당 비용을 줄여 프로그램 성능을 향상시키는 데 활용할 수 있습니다.