البرمجة

تحويل الإشارات باستخدام std::make_unique

عند استخدام الدالة std::make_unique لإنشاء كائن من النوع المشتق (Derived) وتخزينه في مؤشر فريد من نوع std::unique_ptr، هناك بعض التفاصيل التي يجب أن نأخذها في الاعتبار.

في النمط الأول (1)، الذي يعمل، يتم إعادة المؤشر المنشأ مباشرة من std::make_unique() ويتم تحويله ضمن تحويل ضمني إلى std::unique_ptr بسبب عملية التحويل القابلة للتحقق التي تستخدمها C++ للمشتقات. وبما أنه لا يوجد تحويل غير ضمني آخر معقد، فإن الأمر يعمل بشكل صحيح.

أما في الحالة الثانية (2)، التي تفشل في الترجمة، فإن المشكلة تكمن في محاولة إرجاع المؤشر المؤقت auto a، الذي يكون من نوع std::unique_ptr، مباشرة كمؤشر std::unique_ptr في دالة GetDerived2(). يحاول المترجم بناءً على التوقعات تحويل نوع المؤشر، ولكنه يفشل في ذلك لأن النوع المطلوب هو std::unique_ptr والنوع المُقدم هو std::unique_ptr، ولا يوجد تحويل ضمني مباشر بين هذين النوعين.

أما في الحالة الثالثة (3)، فالدالة std::move() تقوم بتحريك الموارد المملوكة بواسطة a إلى المؤشر المُرجع من دالة GetDerived3()، مما يجعل النوع المُرجع متوافقًا مع النوع المتوقع للإرجاع.

في الحالتين الأخيرتين (4)، عند استخدام std::make_unique()، يتم إنشاء كائن من النوع Base، الذي يمكن تحويله ضمنيًا إلى std::unique_ptr بسهولة، وهذا هو السبب في نجاح كل من الحالتين.

بالتالي، يمكن تجاوز مشكلة الحالة الثانية (2) عن طريق استخدام std::move() كما هو موضح في الحالة الثالثة (3)، أو يمكن إصلاحها مباشرة بتحويل نوع المؤشر المؤقت إلى std::unique_ptr في العبارة التي تُرجع القيمة في دالة GetDerived2()، وهذا سيعمل أيضًا بشكل صحيح.

المزيد من المعلومات

بعد فهم الفروق في السلوك بين الحالات المختلفة، يمكننا الآن التفكير في السبب وراء هذا السلوك وكيفية عمل الأمور تحت الغطاء في كل حالة.

في الحالة الأولى (1)، حينما نستخدم std::make_unique()، يتم إنشاء كائن جديد من النوع Derived، ومن ثم يتم تحويل المؤشر المنشأ بواسطة std::make_unique ضمنيًا إلى مؤشر من النوع الأساسي Base. هذا التحويل الضمني يعمل بشكل جيد لأن Derived يرث Base، لذا يمكننا بسهولة استخدام مؤشر من النوع Base للإشارة إلى كائن من النوع Derived.

أما في الحالة الثانية (2)، حيث نخزن المؤشر المؤقت auto a الذي يمتلك نوع std::unique_ptr في متغير من النوع std::unique_ptr، فإن المترجم لا يستطيع تحويل النوع تلقائيًا. يجب علينا بشكل صريح تحويل نوع المؤشر المؤقت a إلى std::unique_ptr ليتمكن المترجم من فهم السياق بشكل صحيح.

في الحالتين الثالثة (3) والرابعة (4)، يتم استخدام std::move() لتحويل ملكية المورد من المؤشر المؤقت a إلى المؤشر المرجع في دالة الإرجاع. يتم تحويل المؤشر بالفعل ضمنيًا إلى النوع المناسب std::unique_ptr بعد استخدام std::move().

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

توضح هذه الحالات كيفية استخدام std::make_unique بالإضافة إلى التحويلات الضمنية واستخدام std::move() لإدارة المؤشرات المؤقتة بشكل صحيح في C++، مما يساعد في فهم السلوك المتوقع وحل المشاكل المحتملة عند استخدام هذه الميزات في الشفرة.

مقالات ذات صلة

زر الذهاب إلى الأعلى
إغلاق

أنت تستخدم إضافة Adblock

يرجى تعطيل مانع الإعلانات حيث أن موقعنا غير مزعج ولا بأس من عرض الأعلانات لك فهي تعتبر كمصدر دخل لنا و دعم مقدم منك لنا لنستمر في تقديم المحتوى المناسب و المفيد لك فلا تبخل بدعمنا عزيزي الزائر