C++

6. STL Placement new

튀김족발 2022. 12. 17. 11:14

C++ STL 중 vector에 값을 넣고 뺄때 push_back을 사용해서 넣는다. 이렇게 넣을때, vector 내부에서는 연결돼있는 배열에 값을 넣고 만약 그 크기가 다 차게 되면 더 많은 메모리를 재 할당하여 사용하게 된다.

 

만약, 여기서 값을 빼고 해제를 하고싶어 delete를 사용해서 중간에 있는 값을 해제하게 되면!?!???!
연결돼있는 배열에서 중간의 값이 빠지면서 메모리가 큰일 날것이다.(안해봐서 모르는데 위험해보이긴 한다. 맨 처음값이 배열의 크기를 담당하는데 연속되는 중간에 값이 없으니까)

 

간단히 알아보자

 

#include <stdio.h>
#include <stdlib.h>
#include <memory>

char buffer[1024];

class KTest
{
	unsigned int _iData;
public:
	KTest()
	{
		_iData = 0x12345678;
		printf("KTest()\r\n");
	}

	~KTest()
	{
		printf("~KTest()\r\n");
	}

private:
	int i = 3;
};

void main()
{
	KTest* p = nullptr;

	p = new KTest();
	p->~KTest();
}

이런식으로 내부구현을 보면 그 값을 delete를 해주는게 아닌, 소멸자만 호출해준다.

 

이렇게 까지는 알겠는데, 외부에서 메모리를 관리하고 있을때, 그 메모리 안에 넣을 경우는 어떻게 할까?

 

void main()
{
	KTest* p = nullptr;
    
	p = new (buffer) KTest();
	p->~KTest();
}

간단하게 placement new를 사용해서 넣게 된다.

이전에 알아본 new를 함수처럼 사용한다.

 

하지만 이 placement new는 new를 재정의하게 되면, 사용할 수 없는 문제가 있다 ㅠㅠ

 

#include <stdio.h>
#include <stdlib.h>
#include <memory>

char buffer[1024];

class KTest
{
	unsigned int _iData;
public:
	KTest()
	{
		_iData = 0x12345678;
		printf("KTest()\r\n");
	}

	~KTest()
	{
		printf("~KTest()\r\n");
	}

	void* operator new(size_t size)
	{
		printf("operator new size = %i\r\n", size);
		return malloc(size);
	}

private:
	int i = 3;
};

void main()
{
	KTest* p = nullptr;
	p = new (buffer) KTest();
	p->~KTest();
}

컴파일 에러가 날것이다.

이럴때는 new 재정의 함수에 저 버퍼와 같은 매개변수를 넣어주면 된다.

#include <stdio.h>
#include <stdlib.h>
#include <memory>

char buffer[1024];

class KTest
{
	unsigned int _iData;
public:
	KTest()
	{
		_iData = 0x12345678;
		printf("KTest()\r\n");
	}

	~KTest()
	{
		printf("~KTest()\r\n");
	}

	void* operator new(size_t size)
	{
		printf("operator new size = %i\r\n", size);
		return malloc(size);
	}
	
	void* operator new(size_t size, char* buffer)
	{
		printf("operator new size = %i\r\n", size);
		return malloc(size);
	}

private:
	int i = 3;
};

void main()
{
	KTest* p = nullptr;
	p = new (buffer) KTest();
	p->~KTest();
}

출력 :

operator new size = 8
KTest()
~KTest()

 

이러면 무리없이 작동 된다.