Updated:

2 minute read

개요

  • 지정한 메모리에 객체를 초기화
  • 메모리 할당과 초기화를 분리하기 위한 기법
  • 메모리 할당 시점에 타입을 정할 수 없거나 초기화 시점을 지정하고 싶은 경우에 사용
    • pool(connection, momory, …), 다형성 등


주의사항

  • placement new 사용 시 delete 대신 소멸자를 직접 호출하고 메모리 해제는 할당한 곳에서 할당 방법에 따른 적절한 해제를 해야함
    • delete의 경우 객체 소멸과 operator delete를 통한 메모리 해제 수행
    • placement new에서 할당한 메모리가 아니기 때문에 객체 소멸만 책임을 지는 것이 논리적


예제

  • 코드
     #include <cstdlib>
     #include <iostream>
     #include <string>
        
     using namespace std;
        
     class Base {
     	protected:
     		int i;
        
     	public:
     		Base(int i) : i(i) { cout << "Base()" << endl; }
     		virtual ~Base() { cout << "~Base()" << endl; }
        
     		virtual void Print() = 0;
     };
        
     class Derived_1 : public Base {
     	private:
     		char c;
        
     	public:
     		Derived_1(int i, char c) : Base(i), c(c) {
     			cout << "Derived_1()" << endl;
     		}
     		virtual ~Derived_1() { cout << "~Derived_1()" << endl; }
        
     		virtual void Print() override {
     			cout << this->i << ", " << this->c << endl;
     		}
        
     		void Func1() { cout << "Func1()" << endl; };
     };
        
     class Derived_2 : public Base {
     	private:
     		string s;
        
     	public:
     		Derived_2(int i, string s) : Base(i), s(s) {
     			cout << "Derived_2()" << endl;
     		}
     		virtual ~Derived_2() { cout << "~Derived_2()" << endl; }
        
     		virtual void Print() override {
     			cout << this->i << ", " << this->s << endl;
     		}
        
     		void Func2() { cout << "Func2()" << endl; };
     };
        
     void malloc_test() {
     	cout << "--- " << __func__ << " start ---" << endl;
        
     	Base *base = static_cast<Base *>(malloc(sizeof(Base) * 1));
        
     	cout << "~~~" << endl;
        
     	Derived_1 *derived = new (base) Derived_1(1, 'a');
        
     	base->Print();
     	derived->Print();
        
     	static_cast<Derived_1 *>(base)->Func1();
        
     	base->~Base();
        
     	free(base);
        
     	cout << "--- " << __func__ << " end ---" << endl;
     }
        
     void calloc_test() {
     	cout << "--- " << __func__ << " start ---" << endl;
        
     	Base *base = static_cast<Base *>(calloc(1, sizeof(Base)));
        
     	cout << "~~~" << endl;
        
     	Derived_1 *derived = new (base) Derived_1(1, 'b');
        
     	base->Print();
     	derived->Print();
        
     	static_cast<Derived_1 *>(base)->Func1();
        
     	base->~Base();
        
     	free(base);
        
     	cout << "--- " << __func__ << " end ---" << endl;
     }
        
     void operator_new_test_1() {
     	cout << "--- " << __func__ << " start ---" << endl;
        
     	Base *base = static_cast<Base *>(operator new(sizeof(Base)));
        
     	cout << "~~~" << endl;
        
     	Derived_2 *derived = new (base) Derived_2(1, "aaa");
        
     	base->Print();
     	derived->Print();
        
     	static_cast<Derived_2 *>(base)->Func2();
        
     	base->~Base();
        
     	operator delete(base);
        
     	cout << "--- " << __func__ << " end ---" << endl;
     }
        
     void operator_new_test_2() {
     	cout << "--- " << __func__ << " start ---" << endl;
        
     	const int size = 3;
        
     	unsigned char pool[sizeof(Derived_2) * size];
        
     	for (int i = 0; i < size; ++i) {
     		new (pool + (sizeof(Derived_2) * i)) Derived_2(i, "a");
     	}
        
     	for (int i = 0; i < size; ++i) {
     		reinterpret_cast<Derived_2 *>(pool + sizeof(Derived_2) * i)->Print();
     	}
        
     	for (int i = 0; i < size; ++i) {
     		reinterpret_cast<Derived_2 *>(pool + sizeof(Derived_2) * i)
     			->~Derived_2();
     	}
        
     	cout << "--- " << __func__ << " end ---" << endl;
     }
        
     int main() {
     	malloc_test();
        
     	cout << endl;
        
     	calloc_test();
        
     	cout << endl;
        
     	operator_new_test_1();
        
     	cout << endl;
        
     	operator_new_test_2();
        
     	return 0;
     }
    
  • 실행 결과
     --- malloc_test start ---
     ~~~
     Base()
     Derived_1()
     1, a
     1, a
     Func1()
     ~Derived_1()
     ~Base()
     --- malloc_test end ---
        
     --- calloc_test start ---
     ~~~
     Base()
     Derived_1()
     1, b
     1, b
     Func1()
     ~Derived_1()
     ~Base()
     --- calloc_test end ---
        
     --- operator_new_test_1 start ---
     ~~~
     Base()
     Derived_2()
     1, aaa
     1, aaa
     Func2()
     ~Derived_2()
     ~Base()
     --- operator_new_test_1 end ---
        
     --- operator_new_test_2 start ---
     Base()
     Derived_2()
     Base()
     Derived_2()
     Base()
     Derived_2()
     0, a
     1, a
     2, a
     ~Derived_2()
     ~Base()
     ~Derived_2()
     ~Base()
     ~Derived_2()
     ~Base()
     --- operator_new_test_2 end ---