فصل مؤشر من shared_ptr؟ [مكرر
-
11-09-2019 - |
سؤال
ممكن مكررة:
كيفية الافراج عن مؤشر من دفعة :: Shared_ptr؟
تقوم وظيفة واجهة بلدي بإرجاع مؤشر إلى كائن. من المفترض أن يكون المستخدم ملكية هذا الكائن. لا أريد إرجاع Boost.Shared_ptr، لأنني لا أريد إجبار العملاء على استخدام دفعة. ومع ذلك، فذلك، أود أن أخزن المؤشر في Shared_Ptr لمنع تسرب الذاكرة في حالة الاستثناءات وما إلى ذلك. يبدو أنه لا توجد وسيلة لفصل مؤشر من مؤشر مشترك. أي أفكار هنا؟
المحلول
ما كنت تبحث عن هو release
وظيفة؛ shared_ptr
ليس لديك وظيفة الإصدار. لكل دليل دفعة:
س: لماذا لا يقدم Shared_ptr وظيفة الإصدار ()؟
لا يستطيع A. Shared_PTR التخلي عن الملكية إلا إذا كان فريدا () لأن النسخة الأخرى ستظل تدمير الكائن.
انصح:
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 مع DICELTRETER.
خياران قد تفكر فيه:
- يمكنك استخدام
std::tr1::shared_ptr
, ، والتي ستطلب لمستخدمي استخدام تطبيق مكتبة C ++ يدعم TR1 أو لاستخدام دفعة؛ على الأقل هذا من شأنه أن يمنحهم الخيار بين الاثنين. - يمكنك تنفيذ الخاصة بك
boost::shared_ptr
- مثل المؤشر المشترك واستخدام ذلك على واجهاتك الخارجية.
قد تنظر أيضا إلى المناقشة في هذا السؤال حول باستخدام دفعة :: Shared_ptr في الواجهة العامة للمكتبة.
نصائح أخرى
هناك دائما وسيلة :-)
هناك بالفعل سبب لعدم توفر طريقة للإفراج ()، لكن ليس من المستحيل إنشاء واحد. اجعل المساند الخاص بك. شيء على خط (لم تقم بالفعل بتجميع التعليمات البرمجية، ولكن هذه هي الفكرة العامة):
template <typename T>
class release_deleter{
public:
release_deleter() : released_(new some_atomic_bool(false)){}
void release() {released_->set(true);}
void operator()(T* ptr){if(!released_->get()) delete ptr;}
private:
shared_ptr<some_atomic_bool> released_;
}
..
shared_ptr<some_type> ptr(new some_type, release_deleter<some_type>());
..
release_deleter<some_type>* deleter = get_deleter<release_deleter<some_type>>(ptr);
deleter->release();
some_type* released_ptr = ptr.get();
من المفترض أن يكون المستخدم ملكية هذا الكائن. أنا لا أريد إرجاع boost.shared_ptr،
shared_ptr
يعبر مشترك الملكية، وتريد واجهةك للتعبير نقل من الملكية. std::auto_ptr
وبالتالي سيكون أكثر قابلية للتطبيق هنا.
ومع ذلك، أود أن أخزن المؤشر في Shared_ptr لمنع تسرب الذاكرة في حالة الاستثناءات
تكرارا، shared_ptr
قد لا تكون أفضل أداة لهذه الوظيفة. لمنع التسريبات في حالة الاستثناءات، scoped_ptr
أو auto_ptr
سيكون مناسبا أفضل.
إستخدم shared_ptr
إلى أ scoped_ptr
إلى المورد (shared_ptr<scoped_ptr<Resource>>
). بهذه الطريقة تحصل عليه shared_ptr
العد المرجعي، الذي سيقوم بتدمير المورد تلقائيا إذا وفقط إذا كان لا يزال مرتبطا scoped_ptr
. وبعد ولكن يمكنك فصل scoped_ptr
عندما تكون مستعدا لتسليم الملكية.
كما جيمس مغطاة جيدا، لا يمكنك فصل مؤشر مشترك.
هل تحتاج إلى أصحاب متعددة داخليا، أم أنك تقوم بنقل الملكية من فصلك إلى العميل؟ في هذه الحالة std::auto_ptr
قد تناسب الفاتورة.
إذا كنت قلقا بشأن دلالات الدهشة std::auto_ptr
, ، يمكنك الاحتفاظ بها داخليا boost::scoped_ptr
, وفصله عند نقطة تسليمه - تتركه إلى العميل لحذفه يدويا أو تخزينه يدويا في مؤشر ذكي خاص به.
إذا كان لديك أصحاب متعددة على جانبكم، فيمكنك استخدام عدد تدخلية. داخليا يمكنك بعد ذلك استخدام boost::intrusive__ptr
, ، ولكن تسليم المؤشر الخام في الواجهة. يمكن للعميل إما أن يعمل يدويا مع عدد التكاليف، أو تخزينه في boost::intrusive_ptr
أنفسهم (لكنك لا تجعلهم يعتمدون عليه)