どのようにリリースのポインタをブー::shared_ptr?
-
20-09-2019 - |
質問
が向上するか::shared_ptrリリースのポインタ格納されずに削除するのですか?
見えないリリース機能が存在するのもよくあるご質問は説明するための、リリース機能のようにすることはできませんでポインタのいないユニークです。私のポインタが異なります。たいのですがリリース私のポインター?または向上のスマートポインタークラスを利用することが出のポインター?んでほしいと願っていない利用auto_ptr:)
解決
あなたが根底にあるポインタを削除しないよう要求することができデリータを使用する必要があります。
となっていた(この答えを参照してください。詳細については)この質問の重複としてマークされます。
他のヒント
やめてください。Boost の FAQ エントリ:
Q. 。なぜshared_ptrはrelease()関数を提供しないのでしょうか?
あ. 共有_ptr 他のコピーは引き続きオブジェクトを破棄するため、 unique() でない限り所有権を譲渡することはできません。
考慮する:
shared_ptr<int> a(new int); shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2 int * p = a.release(); // Who owns p now? b will still call delete on it in its destructor.
さらに、ソースのshared_ptrがカスタムデリータを使用して作成されている可能性があるため、release()によって返されるポインタを確実に割り当て解除することは困難です。
したがって、これがオブジェクトを指す唯一のshared_ptrインスタンスであり(unique()がtrueを返した場合)、オブジェクトが特別なデリータを必要としない場合には、これは安全です。このような .release() 関数を使用した場合、私は依然としてあなたの設計に疑問を抱きます。
あなたは偽デリータを使用することができます。そして、ポインタが実際に削除されることはありません。
struct NullDeleter {template<typename T> void operator()(T*) {} };
// pp of type some_t defined somewhere
boost::shared_ptr<some_t> x(pp, NullDeleter() );
キッズ、自宅でこれをしない。
// set smarty to point to nothing
// returns old(smarty.get())
// caller is responsible for the returned pointer (careful)
template <typename T>
T* release (shared_ptr<T>& smarty) {
// sanity check:
assert (smarty.unique());
// only one owner (please don't play games with weak_ptr in another thread)
// would want to check the total count (shared+weak) here
// save the pointer:
T *raw = &*smarty;
// at this point smarty owns raw, can't return it
try {
// an exception here would be quite unpleasant
// now smash smarty:
new (&smarty) shared_ptr<T> ();
// REALLY: don't do it!
// the behaviour is not defined!
// in practice: at least a memory leak!
} catch (...) {
// there is no shared_ptr<T> in smarty zombie now
// can't fix it at this point:
// the only fix would be to retry, and it would probably throw again
// sorry, can't do anything
abort ();
}
// smarty is a fresh shared_ptr<T> that doesn't own raw
// at this point, nobody owns raw, can return it
return raw;
}
さて、参照カウントのための所有者の総数が> 1であるかどうかを確認する方法はありますか?
のポインタをポイントも、話ができ shared_ptr::reset()
.
しかし、これを削除しオブジェクトを指摘したポインタでの最後の参照のオブジェクトです。しかし、これは正確に希望の行動のポインタ。
れば、ほかの参照の参照が保有していないオブジェクト生きていることができる、 boost::weak_ptr
参照 ブ文書).A weak_ptr
開催への参照オブジェクトがない追加の参照カウントのオブジェクトが削除される場合は弱参照が存在します。
共有の基礎は信頼です。あなたのプログラム内のいくつかのインスタンスは、生のポインタを解放する必要がある場合、それはshared_ptr
が間違った型であることを確認するために、ほとんどです。
しかし、最近私は、あまりにもこれをやってみたかったです。最後に、私はいくつかのstd::shared_ptr
を使用するには、私の古い決定が考え抜かれていなかったことを教えられました。
私は、日常のクリーンアップのためのこのタイプを使用しました。しかし、ポインタは、単にいくつかの場所に複製されました。実際に私はstd::unique_ptr
機能を持っている(驚き)release
を、必要としていました。
彼らはないものを知っているためにそれらを許します。 この例では、ブーストで動作します:: shared_ptrのとMSVSのstd :: shared_ptrのメモリリークなし!
template <template <typename> class TSharedPtr, typename Type>
Type * release_shared(TSharedPtr<Type> & ptr)
{
//! this struct mimics the data of std:shared_ptr ( or boost::shared_ptr )
struct SharedVoidPtr
{
struct RefCounter
{
long _Uses;
long _Weaks;
};
void * ptr;
RefCounter * refC;
SharedVoidPtr()
{
ptr = refC = nullptr;
}
~SharedVoidPtr()
{
delete refC;
}
};
assert( ptr.unique() );
Type * t = ptr.get();
SharedVoidPtr sp; // create dummy shared_ptr
TSharedPtr<Type> * spPtr = (TSharedPtr<Type>*)( &sp );
spPtr->swap(ptr); // swap the contents
ptr.reset();
// now the xxx::shared_ptr is empy and
// SharedVoidPtr releases the raw poiter but deletes the underlying counter data
return t;
}
あなたは私に多くの同じようで共有ポインタを、削除することができます。ポインタは常に一意である場合には、std::auto_ptr<>
は良い選択です。それらの操作は、コピーや一時的な重複の多くを行うため、ユニークなポインタは、STLコンテナで使用することができないことに注意してください。
私はあなたの質問は、これを達成する程度であれば全くわからないんだけど、あなたは1 shared_ptr
から値を解放した場合、同じ値に他のすべての共有ポインタはnullptrなっshared_ptr
、から行動をしたい場合は、そして、あなたはその動作を実現するためにunique_ptr
にshared_ptr
を置くことができます。
void print(std::string name, std::shared_ptr<std::unique_ptr<int>>& ptr)
{
if(ptr == nullptr || *ptr == nullptr)
{
std::cout << name << " points to nullptr" << std::endl;
}
else
{
std::cout << name << " points to value " << *(*ptr) << std::endl;
}
}
int main()
{
std::shared_ptr<std::unique_ptr<int>> original;
original = std::make_shared<std::unique_ptr<int>>(std::make_unique<int>(50));
std::shared_ptr<std::unique_ptr<int>> shared_original = original;
std::shared_ptr<std::unique_ptr<int>> thief = nullptr;
print(std::string("original"), original);
print(std::string("shared_original"), shared_original);
print(std::string("thief"), thief);
thief = std::make_shared<std::unique_ptr<int>>(original->release());
print(std::string("original"), original);
print(std::string("shared_original"), shared_original);
print(std::string("thief"), thief);
return 0;
}
出力:
original points to value 50
shared_original points to value 50
thief points to nullptr
original points to nullptr
shared_original points to nullptr
thief points to value 50
この動作は、このリソースへのすべての参照の共有を無効にしながら、後でそのリソースを再利用し、あなたが(配列のような)リソースを共有することができます。
ここで働くかもしれないハックです。あなたは本当のバインドでない限り、私はそれをお勧めしません。
template<typename T>
T * release_shared(std::shared_ptr<T> & shared)
{
static std::vector<std::shared_ptr<T> > graveyard;
graveyard.push_back(shared);
shared.reset();
return graveyard.back().get();
}
あなたのポインタは確かにユニークであるならば、前者はあなたのコンパイラのために使用できない場合std::unique_ptr
またはboost::scoped_ptr
を使用して行います。それ以外の場合はboost::shared_ptr
とboost::weak_ptr
の使用を組み合わせることを検討してください。詳細についてはブーストドキュメントをチェックしてください。
私は*ポコ:: HTTPRequestHandlerFactory生HTTPRequestHandlerを返すように期待し使用しています、ポコフレームワークは、要求の終了後にハンドラを削除します。
は、また、コントローラを作成するために、DIのソースプロジェクトを使用して、しかし、インジェクタは、(私が直接返すことはできませんのshared_ptrを返し、handler.getを返す)とすぐに、この関数はshared_ptrのを返すようスコープ外になるため、どちらか良くないとそのので、ここで、実行は.release()メソッドを持っているために合理的な(と思う)理由である前に、ハンドラは削除されます。私は次のようにHTTPRequestHandlerWrapperクラスを作成することになった: -
class HTTPRequestHandlerWrapper : public HTTPRequestHandler {
private:
sauce::shared_ptr<HTTPRequestHandler> _handler;
public:
HTTPRequestHandlerWrapper(sauce::shared_ptr<HTTPRequestHandler> handler) {
_handler = handler;
}
virtual void handleRequest(HTTPServerRequest& request, HTTPServerResponse& response) {
return _handler->handleRequest(request, response);
}
};
、その後、工場でしょう。
HTTPRequestHandler* HttpHandlerFactory::createRequestHandler(const HTTPServerRequest& request) {
URI uri = URI(request.getURI());
auto path = uri.getPath();
auto method = request.getMethod();
sauce::shared_ptr<HTTPRequestHandler> handler = _injector->get<HTTPRequestHandler>(method + ":" + path);
return new HTTPRequestHandlerWrapper(handler);
}
ソースとポコの両方を満足し、うまく機能している。
私は、非同期ハンドラによってポインタを渡すと、障害が発生した場合の自己破壊行動を維持するために必要な最終的なAPIは、生のポインタを期待ので、私は、単一のshared_ptrから解放するためにこの関数を作っます:
#include <memory>
template<typename T>
T * release(std::shared_ptr<T> & ptr)
{
struct { void operator()(T *) {} } NoDelete;
T * t = nullptr;
if (ptr.use_count() == 1)
{
t = ptr.get();
ptr.template reset<T>(nullptr, NoDelete);
}
return t;
}
もしあなたが代わりにptr.use_count() != 1
を取得しなければならnullptr
ます。
簡単な解決策は、基準を増加させ、次いでshared_pointerリーク。
boost::shared_ptr<MyType> shared_pointer_to_instance(new MyType());
new boost::shared_ptr<MyType>();
MyType * raw_pointer = shared_pointer_to_instance.get()
これは明らかにshared_ptrのとがMyType *
両方のメモリリークが発生します