728x90
1. 개요
오늘은 C++에 기법인 Placement New에 대해 공부해보도록 하겠습니다.
2. Placement New?
C++에서 placement new는 "이미 할당된 메모리 공간"에 객체를 생성(초기화)하는 문법입니다.
보통의 new 연산자가 [메모리 할당 + 객체 생성]을 동시에 수행한다면, placement new는 할당 단계는 건너뛰고 생성자만 호출하여 객체를 만들어 냅니다.
3. 왜 쓰는가?
주로 성능 최적화와 정밀한 메모리 제어가 필요한 시스템에서 사용합니다.
- 메모리 할당 비용 제거: 힙(Heap)에서 메모리를 할당(malloc 등)하는 과정은 운영체제의 시스템 콜을 거치며 시간이 걸립니다. 이를 피하고 싶을 때 사용합니다.
- 메모리 파편화 방지: 작은 객체를 수없이 생성/삭제하면 메모리가 조각나는데, 미리 큰 메모리 블록(Pool)을 만들어두고 그 안에서 관리하면 이를 방지할 수 있습니다.
- 하드웨어 제어: 임베디드 시스템 등에서 특정 메모리 주소(예: 하드웨어 레지스터)에 객체를 매핑해야 할 때 사용합니다.
4. 장점
- 속도가 매우 빠름: 메모리 할당 단계가 생략되므로 객체 생성 속도가 획기적으로 빨라집니다.
- 캐시 적중률(Cache Hit) 향상: 연속된 메모리 공간에 객체들을 배치하면 CPU 캐시 효율이 높아져 처리 속도가 빨라집니다.
- 재사용성: 할당받은 메모리를 해제하지 않고, 그 자리에 새로운 객체를 덮어씌우는 방식으로 메모리를 재활용할 수 있습니다.
5. 주의할 점
이 부분은 시스템의 안정성과 직결되므로 매우 중요합니다.
- delete 사용 금지:
- delete ptr;을 호출하면 안 됩니다. 이 명령어는 메모리 자체를 운영체제에 반환하려 시도하는데, Placement New로 쓴 메모리는 스택이나 정적 영역일 수도 있기 때문에 충돌(Crash)이 발생합니다.
- 소멸자의 명시적 호출:
- 컴파일러가 자동으로 소멸자를 불러주지 않습니다. 객체 사용이 끝나면 반드시 ptr->~ClassName(); 형태로 소멸자를 직접 호출해야 합니다.
- 메모리 정렬 (Alignment):
- 객체가 저장될 메모리 공간은 해당 객체의 정렬 요건(Alignment requirement)을 만족해야 합니다. 그렇지 않으면 버스 에러가 나거나 성능이 저하될 수 있습니다.
6. 예제 코드
#include <iostream>
#include <string>
class User {
public:
int id;
std::string name;
User(int i, std::string n) : id(i), name(n)
{
std::cout << "User 생성자 호출: " << name << std::endl;
}
~User()
{
std::cout << "User 소멸자 호출: " << name << std::endl;
}
};
int main()
{
char* buffer = new char[sizeof(User)];
std::cout << "--- 객체 생성 시작 ---" << std::endl;
User* userPtr = new (buffer) User(1, "GG");
std::cout << "ID: " << userPtr->id << ", Name: " << userPtr->name << std::endl;
std::cout << "--- 객체 사용 종료 ---" << std::endl;
userPtr->~User();
return 0;
}
7. 결과

또한, 주소가 char* buffer랑 User가 같다는것을 확인할수 있습니다.

8. 번외
참고로 아래처럼 스택에 할당을 할수 있으니, delete는 안사용하는것이 좋습니다.(소멸자만 호출)
#include <iostream>
#include <string>
class User {
public:
int id;
std::string name;
User(int i, std::string n) : id(i), name(n)
{
std::cout << "User 생성자 호출: " << name << std::endl;
}
~User()
{
std::cout << "User 소멸자 호출: " << name << std::endl;
}
};
int main()
{
char buffer[sizeof(User)];
std::cout << "--- 객체 생성 시작 ---" << std::endl;
User* userPtr = new (buffer) User(1, "GG");
std::cout << "ID: " << userPtr->id << ", Name: " << userPtr->name << std::endl;
std::cout << "--- 객체 사용 종료 ---" << std::endl;
userPtr->~User();
return 0;
}

'개발자 면접 공부 > C-C++' 카테고리의 다른 글
| 정규 표현식 (0) | 2025.12.18 |
|---|---|
| 정적 링킹 vs 동적 링킹 (0) | 2024.07.04 |
| 템플릿(Template) (1) | 2024.07.01 |
| C++ 11 범위기반 for문 (for each) (0) | 2024.06.16 |
| extern 쓰는법 (0) | 2024.06.11 |