私はboost :: make_sharedを初めて使用して、共有ポインタが指すオブジェクトを作成しています。主にコードが低すぎて単一の割り当てが実際にパフォーマンスを向上させるのに役立ったためです。boost :: make_sharedが(配置)演算子newを呼び出さない
いくつかのメモリリークを修正した後、私は単純なメモリリークディテクタを実装することを決めました。アプリケーションの特定のポイントでどのオブジェクトがまだ生存しているかをカウントするだけです。これを数回前に実装していて、自分のコードがオブジェクトを検出しなくなったことに驚きました。
私は私がしなければならなかったすべては上書き「配置新しい」ためmake_shared用ブーストウェブサイトのドキュメントから、次の代わりに、「正常な」オペレータ新者のあることを考え出し:
「エフェクト:メモリを割り当て、適切なタイプT と のオブジェクトに対しては、配置式new(pv) T()または新しい(pv)T(std :: forward(args)...)を使用してオブジェクトを構成します。 allocate_shared は、メモリの割り当てにaのコピーを使用します。例外がスローされた場合は、 の効果はありません。
新しいプレースメントも呼び出されません。私は、出力の3行目に「テストは、新しい配置を非投げ」期待していた
...
Global new
Test::Test()
...
Test new
Test::Test()
Global new
...
:以下の出力をレンダリングする
#include <iostream>
using namespace std;
#include "boost/shared_ptr.hpp"
#include "boost/make_shared.hpp"
class Test
{
public:
Test() { cout << "Test::Test()" << endl; }
void* operator new (std::size_t size) throw (std::bad_alloc) {
cout << "Test new" << endl;
return malloc(size);
}
void* operator new (std::size_t size, const std::nothrow_t& nothrow_constant) throw() {
cout << "Test non-throwing new" << endl;
return malloc(size);
}
void* operator new (std::size_t size, void* ptr) throw() {
cout << "Test non-throwing placement new" << endl;
return malloc(size);
}
};
void* operator new (std::size_t size) throw (std::bad_alloc) {
cout << "Global new" << endl;
return malloc(size);
}
int main() {
cout << "..." << endl;
boost::shared_ptr<Test> t1(boost::make_shared<Test>());
cout << "..." << endl;
boost::shared_ptr<Test> t2(new Test());
cout << "..." << endl;
return 0;
}
:私は動作を再現するための小さなテストプログラムを書かれています。その行動はどうあるべきだと思いますか? make_sharedのドキュメントによれば、Testクラスのプレースメントnew演算子を呼び出す必要があることに同意しますか?それとも私はそれを誤解しましたか?
私はブーストの実装をローカルにコピーして、もちろん、プレースメントnew演算子への呼び出しを追加することができます。しかし、それは適切であろうか、それとも新しい配置のセマンティクスに違反するだろうか?
お時間をいただきありがとうございます。
ブーストのを見ると、グローバルプレースメントnew演算子:: new(pv)T()が使用されています。そのため、クラスレベルの配置が呼び出されていないのです... newの前にグローバル修飾子 '::'を削除すると、make_sharedは実際にクラスレベルの配置new演算子を呼び出します。 –
Gob00st