سؤال

في مشروع C ++ يستخدم مؤشرات ذكية، مثل boost::shared_ptr, ، ما هي فلسفة التصميم الجيدة فيما يتعلق باستخدام "this"?

اعتبر ذلك:

  • من الضروري تخزين المؤشر الخام الموجود في أي مؤشر ذكي للاستخدام لاحقا. لقد تخليت من التحكم في حذف الكائن وتثق في المؤشر الذكي للقيام بذلك في الوقت المناسب.

  • أعضاء الطبقة غير الثابتة يستخدمون جوهرون this مؤشر. إنه مؤشر خام ولا يمكن تغييره.

إذا قمت بالتخزين من أي وقت مضى this في متغير آخر أو نقله إلى وظيفة أخرى يمكن أن يحتمل أن يخزنها في وقت لاحق أو ربطه في رد الاتصال، فأنا أخلق الأخطاء التي يتم تقديمها عندما يقرر أي شخص تقديم مؤشر مشترك إلى صفي.

بالنظر إلى ذلك، متى يكون مناسبا لي للاستخدام صراحة this مؤشر؟ هل هناك نماذج تصميم يمكن أن تمنع الأخطاء المتعلقة بهذا؟

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

المحلول

بينما ليس لدي إجابة عامة أو بعض المصطلح، هناك boost::enable_shared_from_this وبعد يتيح لك الحصول على مشاركة مشتركة من إدارة كائن يدير بالفعل بواسطة Shared_ptr. نظرا لأنها في وظيفة العضو، فلن تكون لديك إشارة إلى تلك الإدخال Shared_ptr's، فإنه يتيح لك الحصول على مثيل Shared_Ptr ويمر عندما تحتاج إلى اجتياز هذا المؤشر.

ولكن هذا لن يحل مسألة المرور this من داخل المنشئ، نظرا لأنه في ذلك الوقت، لا يقوم Shared_Ptr بإدارة جسمك بعد.

نصائح أخرى

سؤال خاطئ

في مشروع C ++ يستخدم المؤشرات الذكية

المشكلة لا علاقة لها بالمؤشرات الذكية في الواقع. انها فقط حول الملكية.

المؤشرات الذكية هي مجرد أدوات

لا يغيرون شيئا يربطون مفهوم الملكية، ESP. الحاجة إلى ملكية محددة جيدا في برنامجك, ، حقيقة أن الملكية يمكن نقلها طوعا، ولكن لا يمكن اتخاذها من قبل عميل.

يجب أن تفهم أن المؤشرات الذكية (أيضا الأقفال وغيرها من كائنات الراي) تمثل قيمة وعلاقة WRT هذه القيمة في نفس الوقت. أ shared_ptr هو مرجع إلى كائن وتحديد علاقة: يجب عدم تدمير الكائن قبل ذلك shared_ptr, وعندما هذا shared_ptr يتم تدميره، إذا كان آخر واحد يعرف هذا الكائن، يجب تدمير الكائن على الفور. فيunique_ptr يمكن أن ينظر إليها على أنها حالة خاصة من shared_ptr حيث يوجد صفر التعرج بحكم التعريف، وبالتالي فإن unique_ptr هو دائما آخر واحد يعرف كائن.)

لماذا يجب عليك استخدام المؤشرات الذكية

يوصى باستخدام المؤشرات الذكية لأنهم يعبرون عن الكثير من الإعلانات فقط والمتغيرات والوظائف.

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

حتى في لغات القمامة الوظيفية غير المحتة التي تم جمعها، تحتاج إلى جعل الملكية واضحة: لا تريد الكتابة فوق قيمة كائن إذا كانت مكونات أخرى لا تزال بحاجة إلى القيمة القديمة. هذا صحيح بشكل ملحوظ في Java، حيث مفهوم ملكية هيكل البيانات القابلة للتغيير أمر مهم للغاية في البرامج الخيوط.

ماذا عن مؤشرات الخام؟

استخدام المؤشر الخام لا يعني أنه لا توجد ملكية. لم يتم وصفه فقط بإعلان متغير. يمكن وصفها في التعليقات، في وثائق التصميم الخاصة بك، إلخ.

لهذا السبب يعتبر العديد من مبرمجي C ++ أن استخدام المؤشرات الخام بدلا من المؤشر الذكي المناسب السفلي: لأنه أقل تعبيرية (لقد تجنبت المصطلحات "جيدة" و "سيئة" عن قصد). أعتقد أن نواة Linux ستكون أكثر قابلية للقراءة مع عدد قليل من الكائنات C ++ للتعبير عن العلاقات.

يمكنك تطبيق تصميم محدد مع أو بدون مؤشرات ذكية. سيتم اعتبار التنفيذ الذي يستخدم المؤشر الذكي بشكل مناسب من قبل العديد من مبرمجي C ++.

سؤالك الحقيقي

في مشروع C ++، ما هي فلسفة التصميم الجيدة فيما يتعلق باستخدام "هذا"؟

هذا غامض بفظاعة.

من الخطير تخزين المؤشر الخام للاستخدام لاحقا.

لماذا تحتاج إلى مؤشر للاستخدام لاحقا؟

لقد استسلمت التحكم في حذف الكائنات والثقة في المكون المسؤول للقيام بذلك في الوقت المناسب.

في الواقع، بعض المكونات مسؤولة عن عمر المتغير. لا يمكنك تحمل المسؤولية: يجب نقلها.

إذا قمت بتخزين هذا في متغير آخر أو اجتيازها إلى وظيفة أخرى يمكن أن تخزنها في وقت لاحق أو ربطها في رد الاتصال، فأنا أخلق الأخطاء التي يتم تقديمها عندما يقرر أي شخص استخدام صفي.

من الواضح، نظرا لأن المتصل غير إعلامي بأن الوظيفة ستقوم بإخفاء مؤشر واستخدامه لاحقا دون التحكم في المتصل، فأنت تقوم بإنشاء الأخطاء.

من الواضح أن الحل إما:

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

فقط في الحالة الأولى، قد ينتهي بك الأمر بمؤشر ذكي في تنفيذ الفصل.

مصدر مشكلتك

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

لا تحاول إدخال مؤشرات ذكية كحل قبل أن تكون لديك مشكلة.

قدم فقط مؤشرات ذكية لحل مشكلة محددة محددة جيدا. لأنك لا تصف مشكلة محددة محددة جيدا، لا يمكن مناقشة حل محدد (تنطوي على مؤشرات ذكية أم لا).

مثال واحد للاستخدام الصحيح هو return *this; في وظائف مثل المشغل ++ () والعامل << ().

عند استخدام فئة مؤشر ذكية، فأنت على حق أمر خطير على تعريض مباشرة "this". هناك بعض دروس المؤشر المتعلقة boost::shared_ptr<T> قد يكون ذلك من الاستخدام:

  • boost::enable_shared_from_this<T>
    • يوفر القدرة على إرجاع كائن مؤشر مشترك لنفسه يستخدم نفس بيانات حساب المرجع باعتبارها مؤشر مشترك موجود إلى الكائن
  • boost::weak_ptr<T>
    • يعمل جنبا إلى جنب مع المؤشرات المشتركة، ولكن لا تحمل إشارة إلى الكائن. إذا تجاوزت جميع المؤشرات المشتركة ويتم إصدار الكائن، فسيكون مؤشر ضعيف قادر على معرفة أن الكائن لم يعد موجودا وسيعودك NULL بدلا من مؤشر لذاكرة غير صالحة. يمكنك استخدام مؤشرات ضعيفة للحصول على مؤشرات مشتركة إلى كائن محسوب مرجع صالح.

أيا من هذه من هذه غير مقاومة، بالطبع، لكنهم سيجعلون رمزك على الأقل أكثر استقرارا وآمنا مع توفير الوصول المناسبة والمرجع المرجعي لكائناتك.

إذا كنت بحاجة إلى استخدام this, ، فقط استخدمه صراحة. التفاف المؤشرات الذكية فقط مؤشرات الكائنات الخاصة أنها تملكها - إما حادراunique_ptr) أو بطريقة مشتركة (shared_ptr).

أنا شخصيا أحب استخدام هذه مؤشر عند الوصول إلى متغيرات الأعضاء للفئة. علي سبيل المثال:

void foo::bar ()
{
    this->some_var += 7;
}

انها مجرد مسألة غير ضارة على الطراز. بعض الناس يحبون ذلك، لا يفعل ذلك.

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

هل يمكن أن تخبرنا بما تريد القيام به بالضبط مع المؤشر؟

خيار آخر يستخدم مؤشرات ذكية تدخلية، والعناية بالعد المرجعي داخل الكائن نفسه، وليس المؤشرات. هذا يتطلب المزيد من العمل قليلا، ولكنه في الواقع أكثر كفاءة وسهلة السيطرة.

سبب آخر لتمرير حول هذا هو إذا كنت ترغب في الحفاظ على السجل المركزي لجميع الكائنات. في المنشئ، يدعو كائن طريقة ثابتة للتسجيل بهذا. من المفيد لمختلف آليات النشر / الاشتراك، أو عندما لا تريد أن يحتاج السجل إلى معرفة الأشياء / الفئات الموجودة في النظام.

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