32비트 환경이다.
간단한 클래스 부터 보자
#include <stdio.h>
int buffer[1024] = {0};
class KTest
{
public:
KTest()
{
printf("KTest()\r\n");
}
~KTest()
{
printf("~KTest()\r\n");
}
private:
int i = 3;
};
void main()
{
KTest* p;
p = new KTest;
delete p;
}
출력 :
KTest()
~KTest()
생성자 소멸자를 호출하는 간단한 생성자이다.
C++ 클래스에서 생성자를 호출하여 동적으로 할당할 때
메모리 할당(new) -> 생성자 호출(KTest())
그리고 해제 할때는
소멸자 호출(~KTest()) -> 메모리 해제(delete)
이런 순서로 작동한다.
메모리를 할당 및 해제 하는 명령어는
p = (KTest*)operator new(sizeof(KTest));
operator delete(p);
이렇게 호출 할 수 있다. 하지만,
생성자와 소멸자는 정의할 수 있지만, new와 delete이 부분은 재정의를 해주어야 한다.
#include <stdio.h>
int buffer[1024] = {0};
class KTest
{
public:
KTest()
{
printf("KTest()\r\n");
}
~KTest()
{
printf("~KTest()\r\n");
}
void* operator new(size_t size)
{
printf("operator new(), size = %i\r\n", size);
return buffer;
}
void operator delete(void*p)
{
printf("operator delete(), p = %p\r\n", p);
}
private:
int i = 3;
};
void PrintBuffer()
{
for (int value : buffer)
{
if (value == 0)
{
break;
}
printf("%d, ", value);
}
printf("\r\n");
}
void main()
{
KTest* p;
p = new KTest;
PrintBuffer();
delete p;
}
buffer로 현재까지 할당돼있는 값들을 확인할 수 있게 만들었다.
출력 :
operator new(), size = 4
KTest()
3,
~KTest()
operator delete(), p = 00F7B3D0
new 호출 -> 생성자 그리고 delete 호출 -> 소멸자
이런식으로 재정의 했고, 출력되는 것도 확인 했다.
한번 배열의 new와 delete도 재정의 해보자
#include <stdio.h>
int buffer[1024] = { 0 };
class KTest
{
public:
KTest()
{
printf("KTest()\r\n");
}
~KTest()
{
printf("~KTest()\r\n");
}
void* operator new(size_t size)
{
printf("operator new(), size = %i\r\n", size);
return buffer;
}
void* operator new[](size_t size)
{
printf("operator new[](), size = %i\r\n", size);
return buffer;
}
void operator delete(void* p)
{
printf("operator delete(), p = %p\r\n", p);
}
void operator delete[](void* p)
{
printf("operator delete[](), p = %p\r\n", p);
}
private:
int i = 3;
};
void PrintBuffer()
{
for (int value : buffer)
{
if (value == 0)
{
break;
}
printf("%d, ", value);
}
printf("\r\n");
}
void main()
{
KTest* p;
p = new KTest[5];
PrintBuffer();
delete[] p;
}
출력 :
operator new[](), size = 24
KTest()
KTest()
KTest()
KTest()
KTest()
5, 3, 3, 3, 3, 3,
~KTest()
~KTest()
~KTest()
~KTest()
~KTest()
operator delete[](), p = 0013B3D0
buffer를 출력한 부분을 보면 할당한 갯수 만큼 첫번째 배열이 정해지고, 그 뒤에 그만큼 메모리가 할당된 것을 볼 수 있다.
그러면 delete[]가 아니고 delete를 사용해서 해제하면 어떻게 될까?
출력 :
operator new[](), size = 24
KTest()
KTest()
KTest()
KTest()
KTest()
5, 3, 3, 3, 3, 3,
~KTest()
operator delete(), p = 0013B3D4
정상적으로 해제가 되긴 한다. 어차피 배열의 첫번째 값만큼 해제를 하면 되니까
하지만 문제가 발생하게 된다. 각 배열 값의 소멸자를 호출하지 않게 된다.
new나 delete를 재정의 할때 다른 인자들을 넣어 작업을 해야 할때가 있다. 그럴땐 다른 값들을 인자로 받고 재정의를 해주자
#include <stdio.h>
int buffer[1024] = { 0 };
class KTest
{
public:
KTest()
{
printf("KTest()\r\n");
}
~KTest()
{
printf("~KTest()\r\n");
}
void* operator new(size_t size)
{
printf("operator new(), size = %i\r\n", size);
return buffer;
}
void* operator new(size_t size, const char* msg, int iValue)
{
printf("operator new(const char*, int), size = %i, msg = %s, iValue = %i\r\n", size, msg, iValue);
return buffer;
}
void operator delete(void* p)
{
printf("operator delete(), p = %p\r\n", p);
}
void* operator new[](size_t size)
{
printf("operator new[](), size = %i\r\n", size);
return buffer;
}
void operator delete[](void* p)
{
printf("operator delete[](), p = %p\r\n", p);
}
private:
int i = 3;
};
void PrintBuffer()
{
for (int value : buffer)
{
if (value == 0)
{
break;
}
printf("%d, ", value);
}
printf("\r\n");
}
void main()
{
KTest* p;
p = new ("Hello", 4) KTest;
PrintBuffer();
delete p;
}
출력 :
operator new(const char*, int), size = 4, msg = Hello, iValue = 4
KTest()
3,
~KTest()
operator delete(), p = 00E6B3D0
뀼
'C++' 카테고리의 다른 글
7. CRTP, Static Plymophism and Rebind (0) | 2023.01.09 |
---|---|
6. STL Placement new (0) | 2022.12.17 |
4. Operator Overloading Ostream (0) | 2022.12.14 |
3. Operator Overloading Function (0) | 2022.12.14 |
2. Base From Member Idiom (0) | 2022.12.04 |