C++ 11 (c++98/03 標準にも当てはまります) 標準 (以下を参照) から、既に定義されているため、新しい関数の演算子をグローバル空間に配置することはできません。
18.6.1.3 配置フォーム [new.delete.placement]
これらの関数は予約済みです。C++ プログラムは、標準 C++ ライブラリ (17.6.4) のバージョンを置き換える関数を定義できません。(3.7.4) の規定は、演算子 new および演算子削除のこれらの予約配置形式には適用されません。
これは、以下のスニペットのポイント 2> によって証明されており、予想どおりにコンパイル エラーが発生します。
しかし、クラスレベルで新しい配置をオーバーライドすることはできます。これは正常に機能します。以下のスニペットのポイント (2) を参照してください。何故ですか?標準に従って、(2) も防止しようとするべきではありません。
以下のスニペットを参照してください。
class Test
{
public:
Test(int i):m_i(i) { cout << "Test::Test()" << endl; }
~Test() { cout << "Test::~Test()" << endl; }
//(1)class level override placement new
void* operator new (std::size_t size) throw (std::bad_alloc) {
cout << "My class level new" << endl;
return malloc(size);
}
//(2)class level override placement new
void* operator new (std::size_t size, void* ptr) throw() {
cout << "My class level non-throwing placement new" << endl;
return ptr;
}
private:
int m_i;
};
//<1>global replacement for operator new - single object form
void* operator new (std::size_t size) throw (std::bad_alloc) {
cout << "My global new" << endl;
return malloc(size);
}
//<2>global replacement for operator new - replcement form
//NB. This is a attempt that definitely fails according to c++ stadnard:
//does get compile error: error: redefinition of 'void* operator new(std::size_t, void*)'
/*
void* operator new (std::size_t size, void* ptr) throw() {
cout << "My global non-throwing placement new" << endl;
return ptr;
}
*/
int main() {
Test* p = new Test(1);
delete p;
cout << "" << endl;
void* mem = operator new(sizeof(Test));
Test* p2 = new(mem) Test(1);
p2->~Test();
operator delete (mem);
return 0;
}
以下は、期待どおりの出力です。
My class level new
My global new
Test::Test()
Test::~Test()
My global new
My class level non-throwing placement new
Test::Test()
Test::~Test()
================================================== ================================ 私の質問に対するさらなる説明:
18.6.1.3 配置形式これらの関数は予約されています。C++ プログラムは、標準C++ ライブラリ (17.6.4)のバージョンを置き換える関数を定義できません 。(3.7.4) の条項は、これらの予約済み配置フォームには適用されません。
operator new および operator delete の。
これは、私のスニペットのポイント <2> で予想されるコンパイル エラーを説明しているので、これは問題ありません。
しかし、クラスの明確化内のポイント (2) でクラス レベルのプレースメント フォームを置き換えることができるのはなぜですか?