C++のoperator new/operator deleteについて
C++のoperator new/operator deleteについて紹介します。
1.サンプル
まず最初にサンプルをご覧ください。
#include <cstdio>
#include <cstdlib>
class Test {
private:
int number;
public:
Test(int num) {
number = num;
std::printf("constructor: %d\n", number);
}
~Test() {
std::printf("destructor\n");
}
void* operator new(std::size_t sz) {
std::printf("operator new: %zu\n",sz);
return std::malloc(sz);
}
void operator delete(void* ptr) {
std::printf("operator delete: %p\n", ptr);
std::free(ptr);
}
};
int main() {
Test* test = new Test(100);
delete test;
}
このサンプルを元にoperator new/operator deleteについて紹介します。
2.operator new/operator deleteとは
operator new/operator deleteは、コンストラクタ起動時、特定のエリアからメモリを確保(または解放)するための仕組みです。
通常のコンストラクタは、
- メモリの割当
- オブジェクトの構築
という2つの動作を行いますが、operator newはメモリの割り当てを実行します。
サンプルでは下記の部分になります。
void* operator new(std::size_t sz) {
std::printf("operator new: %zu\n",sz);
return std::malloc(sz);
}
引数の"size_t"はC++の仕様で決められたもので、オブジェクトのサイズになります。
ユーザーがコンストラクタ起動時にパラメータにサイズを指定する必要はありません(おそらくコンパイラ時にオブジェクトのサイズが分かる)。
また、戻り値の型は"void *"です。
operator deleteは下記の部分です。
void operator delete(void* ptr) {
std::printf("operator delete: %p\n", ptr);
std::free(ptr);
}
引数は確保したアドレスになります。こちらもデストラクタ起動時のパラメータに指定する必要はありません。
3.newとoperator newの違い
operator newはnewのオーバーロード(引数や戻り値が異なるが名称が同一のメソッドを複数定義すること)ですが、operator newとnewが存在する場合、順番に起動されることから、個人的には通常のオーバーロードとは動作が異なる気がします。
具体的には、ユーザープログラムがコンストラクタを実行すると、先にoperator newが起動されてメモリ確保等を行い、その後通常のコンストラクタが起動するようになっています。
デストラクタの動作はその逆で、先に通常のデストラクタが起動され、operator deleteが動作してメモリ解放を行います。
サンプルで説明すると、mainに記述した、
Test* test = new Test(100);
が実行されることで、最初に、
void* operator new(std::size_t sz) { ... }
が起動してmallocでメモリを確保し、その後
Test(int num) { ... }
が起動します。
サンプルの実行結果は下記のようになります。
operator new: 4
constructor: 100
address: 0x12a9010
destructor
operator delete
「4」というのは、クラスで定義した変数
int number;
のサイズになります。
4.参考サイト
参考サイトは下記です。ありがとうございました。