自分のoperator newとoperator deleteを定義する際の注意点


先日、自分がメモリ管理ツールを書いていたとき、どうやって手をつけたのかわからず、C++Primerにメモリ管理の例CacheObjectがあったことを思い出しました.この例はちょっと問題がありますが(メモリが漏れています)、スタート者としては、まあいい例です.復習してみると、いくつか注意が必要なことに気づきました.
第一に、operator newとoperator deleteの宣言:
void* operator new(size_t)
void* operator new[](size_t)
void operator delete(void*)
void operator delete[](void*)

オペレータを再定義する場合、オペレータのパラメータの多くはoperator+:
Type operator+(const Type& lhs, const Type& rhs);

パラメータタイプはoperator+の左と右の2つのオペランドタイプです.しかしoperator newのパラメータは特殊でsizeですtタイプは、通常のオペランドタイプではなく、範囲サイズタイプです.私の観点から理解すると、operator newはメモリ開発者として、主にプログラマーのためにどれだけのメモリを開発しているのか、だから操作数のタイプを知る必要はありません.操作数の大きささえ分かればいいのです.
第二に、operator newとoperator deleteはメンバー関数として、静的関数です.
ここでまずCacheObjectのコードを貼り付けます
#ifndef CHACHEOBJECT_H
#define CHACHEOBJECT_H

#include <allocators>
//#include <memory>
#include <exception>

template<typename T>
class CacheObject
{
public:
	void* operator new(std::size_t);
	void operator delete(void *);
protected:
	T* next;	//              
private:
	static void add_to_freelist(T* p);	//           
	static std::allocator<T> alloc_mem;	// allocator  
	static T* free_pointer;	//        
	static const std::size_t chunk = 50;	//           50 * sizeof(T)
};

template<typename T> std::allocator<T> CacheObject<T>::alloc_mem;
template<typename T> T* CacheObject<T>::free_pointer = 0;

template<typename T>
void CacheObject<T>::add_to_freelist(T* p)
{
	p->CacheObject<T>::next = free_pointer;
	free_pointer = p;
}

template<typename T>
void* CacheObject<T>::operator new(std::size_t n)
{
	if(sizeof(T) != n)
	{
		throw std::runtime_error("Type's size isn't match with CacheObject's size");
	}
	if(!free_pointer)
	{
		T* new_mem = static_cast<T*>(alloc_mem.allocate(chunk));
		for(std::size_t i = 0; i < chunk; ++i)
			add_to_freelist(&new_mem[i]);
	}
	this->chunk;
	T* p = free_pointer;
	free_pointer = free_pointer->CacheObject<T>::next;
	return p;
}

template<typename T>
void CacheObject<T>::operator delete(void *p)
{
	if(p)
		add_to_freelist(static_cast<T*>(p));
}

#endif

この一言に
static void add_to_freelist(T* p);	//    T               

最初はstaticの声明はありませんでしたが
void add_to_freelist(T* p);	//    T               
やっぱりfree_pointerはadd_で静的メンバー変数ですto_freelist関数では、割り当てられていないメモリを指し、CacheObjectオブジェクトごとにadd_を呼び出します.to_freelist、free_pointerの予定通りの仕事.では、次はコンパイルです.
「CacheObject::add_to_freelist」:非静的メンバー関数の不正呼び出しこれがvsから与えられた結果であり、operator new関数のadd_を指すto_freelistこれと同じ
	if(!free_pointer)
	{
		T* new_mem = static_cast<T*>(alloc_mem.allocate(chunk));
		for(std::size_t i = 0; i < chunk; ++i)
			add_to_freelist(&new_mem[i]);
	}

「非静的メンバー関数の不正呼び出し」とは、非静的メンバー関数が静的メンバー関数として呼び出され、不正なエラーが発生することを意味します.最初はおかしいと思いましたoperator newという関数では静的と宣言していませんadd_to_freelistはまた普通のメンバー関数で、まさかメンバー関数がメンバー関数を呼び出すのは間違っていますか?私はネットで長い間良い答えを探していませんでした.その後、私は本を放して、ソースコードを参考にして、add_を発見しました.to_freelistの宣言でC++primerの著者はstatic関数を宣言した.本のように、私もstatic声明をつけて、コンパイルは通過しました!!静的関数ではなくstaticと宣言すると通過できないのはなぜですか?現在のエラーが「非静的メンバー関数が静的メンバー関数として呼び出され、不正なエラーが発生した」と述べているので、私が現在知っているのは2つの可能性があります.1、非静的add_to_freelistはクラスの役割ドメイン外で役割ドメインオペレータ(::)に参照され、明らかに現在の状況はそうではない;2、非静的add_to_freelist関数はoperator newで識別できない.識別できない最大の原因はoperator newが静的関数であり、this指針が欠けている.私の考えを証明するために、私は以下の変化をする.
if(!free_pointer)
	{
		T* new_mem = static_cast<T*>(alloc_mem.allocate(chunk));
		for(std::size_t i = 0; i < chunk; ++i)
			this->add_to_freelist(&new_mem[i]);
	}

非静的add_to_freelistの前にthisを追加すると、コンパイルは結果を出します.
「this」:非静的メンバー関数の内部参照のみ
私もoperator deleteで同じテストをしましたが、結果は以上の結果と同じです.
結論:operator newとoperator deleteは静的反省であり、なぜこの2つのオペレータはデフォルトの静的であるのか.
私たちの普段のコードから考えると
Type *t = new t;
delete t;

operator newが静的でない場合、上のnewの書き方は不正です.オブジェクトは静的関数ではなく作成されていません.静的メンバーデータはクラスに関連付けられており、クラスオブジェクトに関連付けられていないため、プログラムの開始時に存在します.そのため、operator newはどこでも呼び出すことができます.この観点からoperator newの静的設計の妥当性を体現している.
初めてのオリジナル技術ブログですが、ははは、用語の不備や間違いがたくさんあります.皆さんの指摘と批判を歓迎します.