حذف الكائنات إرسال عن طريق الإشارات ، ملكية الكائنات في الإشارات ، QT

StackOverflow https://stackoverflow.com/questions/3183826

سؤال

هنا ، إعلان الإشارة الخاص بي:

signals:
    void mySignal(MyClass *);

وكيف أستخدمه:

MyClass *myObject=new myClass();
emit mySignal(myObject);

هنا تأتي مشكلتي: من المسؤول عن حذف myobject:

  1. رمز المرسل ، ماذا لو تم حذفه قبل استخدام myobject؟ مؤشر متدلي

  2. الفتحة المتصلة بالإشارة ، ماذا لو لم تكن هناك فتحة أو أكثر من فتحة واحدة متصلة بالإشارة؟ تسرب الذاكرة أو المؤشر المتدلي

كيف تدير QT هذا الموقف في إشارات البناء؟ هل تستخدم العد المرجعي الداخلي؟

ما هي أفضل ممارساتك؟

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

المحلول

يمكنك توصيل إشارة بالعديد من الفتحات التي تريدها ، لذا يجب عليك التأكد من أن أيا من هذه الفتحات قادر على فعل شيء لا تريد أن يفعله مع كائنك:

  • إذا قررت تمرير مؤشر كمعلمة ، فسوف تقوم بتشغيل المشكلات التي تصفها ، وإدارة الذاكرة - هنا لا أحد يستطيع العمل من أجلك حيث سيتعين عليك وضع سياسة للتعامل مع التخصيص/الحذف. لبعض الأفكار حول كيفية معالجة هذا راجع قواعد إدارة الذاكرة في كوم العالمية.
  • إذا قررت تمرير معلمة كمرجع ، فلا داعي للقلق بشأن إدارة الذاكرة ولكن فقط حول فتحات تعديل كائنك بطرق غير متوقعة. لا تمر IDEEA بتمرير مؤشرات إلا إذا كان عليك - بدلاً من ذلك استخدام المراجع إذا استطعت.
  • إذا قررت تمرير أ const المرجع إذن ، بناءً على نوع الاتصال الخاص بك ، ستقرير QT قيمة الكائن لك (انظر هذه للحصول على بعض التفاصيل)
  • تجنب أي مشاكل ومرر بالقيمة :)

انظر أيضا هذا سؤال لبعض الأفكار حول تمرير المؤشرات في الإشارات.

نصائح أخرى

لسؤالك الأول ، استخدم qpointer

لسؤالك الثاني ،

إذا فهمت بوضوح ، حتى لو كنت ترسل myObject, ، أنت لا يزال لديك المرجع myObject في الفصل الذي تنبعث منه الإشارة. ثم كيف سيكون تسرب الذاكرة أو مؤشر متدلي؟ لا يزال بإمكانك التمكن من ال myObject من الفصل المنبعث ، أليس كذلك؟

أتمنى أن أكون واضحا ..

يحرر :

من تعليقاتك ، أعتقد أنك ستصدر/حذف الكائنات في الفتحات. الآن أفترض أن مشكلتك هي ، ماذا لو تم استدعاء فتحة (إطلاق الذاكرة) مرة واحدة ، مرتين أو لا يتم استدعاؤها على الإطلاق.

يمكنك استخدام qpointer لذلك. من وثائق QT ،

مؤشرات محمية (QPointer) مفيدة كلما احتجت إلى تخزين مؤشر إلى QObject هذا مملوك لشخص آخر ، وبالتالي قد يتم تدميره بينما لا تزال تحتفظ به. يمكنك اختبار المؤشر بأمان من أجل الصلاحية.

مثال من وثائق QT نفسها ،

     QPointer<QLabel> label = new QLabel;
     label->setText("&Status:");
     ...
     if (label)
         label->show();

يمتد التفسير مثل هذا ..

إذا تم حذف QLABEL في هذه الأثناء ، فسيعقد متغير التسمية 0 بدلاً من عنوان غير صالح ، ولن يتم تنفيذ السطر الأخير أبدًا. هنا سيكون Qlabel الخاص بك MyClass والتسمية هو الخاص بك myObject. وقبل استخدامه تحقق من بطلان.

في 1): يجب أن يهتم المرسل. عند إرسال الإشارة بشكل متزامن (بدلاً من قائمة الانتظار) ، لا يزال الكائن على قيد الحياة عندما يستقبلها المتلقي. إذا احتاج المتلقي إلى تخزينه ، فإن QPointer فقط سيساعد ، ولكن بعد ذلك يحتاج MyClass إلى الاستخلاص من Qobject ، والذي يبدو خاطئًا من السياق. على أي حال ، هذه قضية عامة العمر ، وليس الإشارة/الفتحة للغاية.

البدائل: استخدم فئة القيمة وأرسلها عبر Const Reference. إذا كان بإمكان MyClass فئات فرعية ، فسيتم تمرير Const QsharedPointer

حول Deletelater: DeLetelater () لا يساعد هنا. من شأنه أن يجعل الاتصالات في قائمة الانتظار أكثر أمانًا ، وللتوصيلات المباشرة ، لا يوجد فرق. الاستخدام الذي يأتي فيه Deletelater () هو إذا كان المتلقي يحتاج إلى حذف المرسل. بعد ذلك ، يجب على المرء دائمًا استخدام Deletelater () ، حتى يتمكن المرسل من إكمال ما كان يفعله ، والذي سيتعطل.

في كلمة (حسنا ، اسم الوظيفة) - deletelater () :) جميع qobjects لديها. سيحدد كائن الحذف ، وسيحدث ذلك بعد ذلك في تحديث حلقة الحدث التالي.

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