2 분 소요

개요

  • 지정한 메모리에 객체를 초기화
  • 메모리 할당과 초기화를 분리하기 위한 기법
  • 메모리 할당 시점에 타입을 정할 수 없거나 초기화 시점을 지정하고 싶은 경우에 사용
    • 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 ---