std::make_shared
は基本的には効率的だけど弱点もあるよ,って話.
struct Huge { int data[1024][1024]; }; #include <memory> #include <vector> int main() { std::vector<std::weak_ptr<Huge>> vec; for( int i = 0; i < 100000; ++i ) { auto p = std::make_shared<Huge>(p); vec.push_back(p); p.reset(); // *p の寿命はここで切れるけど, weak_ptr が残ってる限りメモリ領域は解放されない // 結果,メモリを食いつぶしてしまう // std::shared_ptr<Huge> p( new Huge() ); // なら問題ない } }
殆どの実装では, std::weak_ptr
は 参照カウントを確認することで 対象のオブジェクトが破棄されたか否かを判別している.
std::make_shared
は,オブジェクトと参照カウントを一回のメモリ確保で連続した領域に確保するため,
std::weak_ptr
が残っている限り,参照カウントのメモリ領域は解放することができず,
従って,それと同時に確保されたオブジェクトのメモリ領域も解放することができない,という理屈.
一応,領域を動かさずに realloc することは可能だけど,そうしてくれる処理系ってあるんだろうか?
少なくとも標準の realloc では,領域を縮める場合でも領域移動が起きる可能性があるので無理.
また,その場合でも, allocate_shared
には対応できないので ぐぬぬ