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