سؤال

أنا أستفيد على نطاق واسع من boost:shared_ptr في الكود الخاص بي.في الواقع، يتم الاحتفاظ بمعظم الكائنات المخصصة في الكومة بواسطة a shared_ptr.لسوء الحظ، هذا يعني أنني لا أستطيع المرور this في أي وظيفة تأخذ shared_ptr.خذ بعين الاعتبار هذا الرمز:

void bar(boost::shared_ptr<Foo> pFoo)
{
    ...
}

void Foo::someFunction()
{
    bar(this);
}

هناك مشكلتان هنا.أولاً، لن يتم تجميع هذا لأن مُنشئ T* لـ shared_ptr صريح.ثانيا، إذا أجبرته على البناء مع bar(boost::shared_ptr<Foo>(this)) سأقوم بإنشاء مؤشر مشترك ثانٍ للكائن الخاص بي والذي سيؤدي في النهاية إلى الحذف المزدوج.

وهذا يقودني إلى سؤالي:هل هناك أي نمط قياسي للحصول على نسخة من المؤشر المشترك الحالي الذي تعلم أنه موجود من داخل إحدى الطرق على أحد تلك الكائنات؟هل يعد استخدام المرجع المتطفل خياري الوحيد هنا؟

هل كانت مفيدة؟

المحلول

يمكنك أن تستمد من Enable_shared_from_this وبعد ذلك يمكنك استخدام "shared_from_this()" بدلاً من "هذا" لإنتاج مؤشر مشترك للكائن الذاتي الخاص بك.

المثال في الرابط:

#include <boost/enable_shared_from_this.hpp>

class Y: public boost::enable_shared_from_this<Y>
{
public:

    shared_ptr<Y> f()
    {
        return shared_from_this();
    }
}

int main()
{
    shared_ptr<Y> p(new Y);
    shared_ptr<Y> q = p->f();
    assert(p == q);
    assert(!(p < q || q < p)); // p and q must share ownership
}

إنها فكرة جيدة عند إنشاء سلاسل رسائل من وظيفة عضو لتعزيز::ربط إلى Shared_from_this() بدلاً من ذلك.سيضمن عدم تحرير الكائن.

نصائح أخرى

ما عليك سوى استخدام مؤشر أولي لمعلمة وظيفتك بدلاً من Shared_ptr.الغرض من المؤشر الذكي هو التحكم في عمر الكائن، ولكن عمر الكائن مضمون بالفعل من خلال قواعد تحديد النطاق في لغة C++:سيكون موجودًا على الأقل طالما انتهت وظيفتك.أي أنه لا يمكن لرمز الاستدعاء حذف الكائن قبل عودة وظيفتك؛وبالتالي يتم ضمان سلامة المؤشر "الغبي"، طالما أنك لا تحاول حذف الكائن الموجود داخل وظيفتك.

المرة الوحيدة التي تحتاج فيها إلى تمرير Shared_ptr إلى دالة هي عندما تريد تمرير ملكية الكائن إلى الدالة، أو تريد أن تقوم الدالة بعمل نسخة من المؤشر.

لدى Boost حل لحالة الاستخدام هذه، تحقق Enable_shared_from_this

هل تقوم بالفعل بإنشاء المزيد من النسخ المشتركة من pFoo داخل الشريط؟إذا كنت لا تفعل أي شيء مجنون في الداخل، فقط قم بما يلي:


void bar(Foo &foo)
{
    // ...
}

مع سي++11 shared_ptr و enable_shared_from_this موجود الآن في المكتبة القياسية.والأخير، كما يوحي الاسم، مخصص لهذه الحالة بالضبط.

http://en.cppreference.com/w/cpp/memory/shared_ptr

http://en.cppreference.com/w/cpp/memory/enable_shared_from_this

أسس المثال على ذلك في الروابط أعلاه:

struct Good: std::enable_shared_from_this<Good>{
    std::shared_ptr<Good> getptr() {
        return shared_from_this();
    }
};

يستخدم:

std::shared_ptr<Good> gp1(new Good);
std::shared_ptr<Good> gp2 = gp1->getptr();
std::cout << "gp2.use_count() = " << gp2.use_count() << '\n';

تريد الوظيفة التي تقبل المؤشر القيام بأحد السلوكين:

  • تملك الكائن يتم تمريره، وحذفه عندما يخرج عن النطاق.في هذه الحالة، يمكنك فقط قبول X* ولف نطاقscoped_ptr على الفور حول هذا الكائن (في نص الدالة).سيعمل هذا على قبول "هذا" أو بشكل عام أي كائن مخصص للكومة.
  • مشاركة المؤشر (لا تملكه) إلى الكائن الذي يتم تمريره.في هذه الحالة عليك أن تفعل لا تريد استخدامscoped_ptr على الإطلاق، لأنك لا تريد حذف الكائن في نهاية وظيفتك.في هذه الحالة، ما تريده نظريًا هو Shared_ptr (لقد رأيته يُسمى Linked_ptr في مكان آخر).مكتبة التعزيز لديها نسخة من Shared_ptr, ، وهذا موصى به أيضًا في كتاب سكوت مايرز لـ C++ الفعال (البند 18 في الطبعة الثالثة).

يحرر: عفوًا، لقد أخطأت في قراءة السؤال قليلاً، وأرى الآن أن هذه الإجابة لا تعالج السؤال بالضبط.سأترك الأمر على أي حال، في حال كان هذا مفيدًا لأي شخص يعمل على كود مماثل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top