c++ معنى - ما هو المؤشر الذكي ومتى يجب أن أستخدمه؟




كلمة بالعربي (13)

ما هو المؤشر الذكي ومتى يجب أن أستخدمه؟


Answers

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

مقدمة صغيرة متاحة على الصفحة الذكية مؤشرات - ما ، لماذا ، وماذا؟ .

أحد أنواع المؤشرات الذكية البسيطة هو std::auto_ptr (الفصل 20.4.5 من معيار C ++) ، والذي يسمح std::auto_ptr تخصيص الذاكرة تلقائيًا عندما يكون خارج النطاق ويكون أكثر قوة من استخدام المؤشر البسيط عند طرح استثناءات ، على الرغم من أنه أقل مرونة.

نوع آخر مناسب هو boost::shared_ptr الذي يطبق عد الإشارة ويقوم تلقائيًا بإلغاء تخصيص الذاكرة عند عدم وجود أي مراجع للكائن. هذا يساعد على تجنب تسرب الذاكرة وهو سهل الاستخدام لتنفيذ RAII .

يتم تغطية الموضوع بعمق في كتاب "C ++ Templates: The Complete Guide" للكاتب David Vandevoorde، Nicolai M. Josuttis ، Chapter Chapter 20. Smart Pointers. بعض الموضوعات المشمولة:

  • حماية ضد الاستثناءات
  • أصحاب ، (ملاحظة ، std::auto_ptr هو تنفيذ هذا النوع من مؤشر الذكية)
  • تكوين المورد هو التهيئة (يتم استخدام هذا بشكل متكرر لإدارة موارد الاستثناءات الآمنة في C ++)
  • قيود حامل
  • العد مرجع
  • الوصول المتزامن المضاد
  • التدمير وإلغاء التوزيع

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


يشبه المؤشر الذكي مؤشرًا عاديًا (مكتوبًا) ، مثل "char *" ، باستثناء عندما يخرج المؤشر نفسه من النطاق ، ثم يتم حذف ما يشير إليه أيضًا. يمكنك استخدامه كما لو كنت مؤشرًا عاديًا ، باستخدام "->" ، ولكن ليس إذا كنت تحتاج إلى مؤشر فعلي للبيانات. لذلك ، يمكنك استخدام "& * ptr".

من المفيد لـ:

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

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

قد لا ترغب في استخدام مؤشر ذكي عندما:

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

أنظر أيضا:


تعالج معظم أنواع المؤشرات الذكية التخلص من كائن المؤشر لك. إنه سهل للغاية لأنه ليس عليك التفكير في التخلص من الأشياء يدويًا بعد الآن.

المؤشرات الذكية الأكثر شيوعاً هي std::tr1::shared_ptr (أو boost::shared_ptr ) ، والأقل شيوعا ، std::auto_ptr . أوصي بالاستخدام المنتظم لـ shared_ptr .

shared_ptr متعددة الاستخدامات للغاية ويتعامل مع مجموعة كبيرة من سيناريوهات التخلص ، بما في ذلك الحالات التي تحتاج فيها الكائنات إلى "المرور عبر حدود DLL" (حالة الكابوس الشائعة إذا تم استخدام libc s مختلفة بين التعليمات البرمجية الخاصة بك و DLLs).


إليك إجابة بسيطة لهذه الأيام من C ++ الحديثة:

  • ما هو المؤشر الذكي؟
    إنه نوع من القيمة التي يمكن استخدامها كمؤشر ، ولكنه يوفر ميزة إضافية لإدارة الذاكرة التلقائية: عندما لا يكون المؤشر قيد الاستخدام ، يتم إلغاء تحديد الذاكرة التي تشير إليها (انظر أيضًا التعريف الأكثر تفصيلاً في Wikipedia ).
  • متى يجب علي استخدام واحدة؟
    في الكود الذي ينطوي على تتبع ملكية قطعة من الذاكرة ، تخصيص أو إلغاء التخصيص ؛ غالباً ما يوفر لك المؤشر الذكي الحاجة إلى القيام بهذه الأشياء بشكل صريح.
  • ولكن ما هو المؤشر الذكي الذي ينبغي استخدامه في أي من هذه الحالات؟
    • استخدم std::unique_ptr عندما لا تنوي الاحتفاظ بمراجع متعددة لنفس الكائن. على سبيل المثال ، استخدمه لمؤشر للذاكرة يتم تخصيصه عند إدخال بعض النطاق وتخصيصه عند الخروج من النطاق.
    • استخدم std::shared_ptr عندما تريد الإشارة إلى الكائن الخاص بك من أماكن متعددة - ولا تريد أن يتم إلغاء تخصيصها حتى تختفي كل هذه المراجع.
    • استخدم std::weak_ptr عندما ترغب في الإشارة إلى الكائن الخاص بك من أماكن متعددة - لتلك المراجع التي يكون من المناسب تجاهلها std::weak_ptr (بحيث يتم فقط ملاحظة أن الكائن قد اختفى عند محاولة حدوث dereference).
    • لا تستخدم المؤشرات boost:: smart أو std::auto_ptr إلا في الحالات الخاصة التي يمكنك قراءتها إذا كان يجب عليك.
  • مهلا ، أنا لم أطلب أي واحد لاستخدام!
    آه ، لكنك أردت حقًا ، اعترف بذلك.
  • لذلك متى يجب علي استخدام المؤشرات العادية بعد ذلك؟
    في الغالب في التعليمات البرمجية غافلين عن ملكية الذاكرة. هذا عادة ما يكون في الوظائف التي تحصل على مؤشر من مكان آخر ولا تخصيص أو إلغاء تخصيص أو تخزين نسخة من المؤشر الذي outlasts تنفيذ الخاصة بهم.

دع T يكون فئة في هذا البرنامج التعليمي يمكن تقسيم المؤشرات في C ++ إلى 3 أنواع:

1) مؤشرات الخام :

T a;  
T * _ptr = &a; 

لديهم عنوان ذاكرة إلى موقع في الذاكرة. استخدم بحذر ، حيث تصبح البرامج معقدة من الصعب تتبعها.

المؤشرات التي تحتوي على بيانات أو عنوان const {اقرأ للخلف}

T a ; 
const T * ptr1 = &a ; 
T const * ptr1 = &a ;

المؤشر إلى نوع البيانات T الذي هو const. بمعنى أنه لا يمكنك تغيير نوع البيانات باستخدام المؤشر. أي *ptr1 = 19 ؛ لن يعمل. ولكن يمكنك تحريك المؤشر. أي ptr1++ , ptr1-- ؛ الخ سوف تعمل. قراءة للخلف: مؤشر إلى نوع T الذي هو const

  T * const ptr2 ;

مؤشر const إلى نوع البيانات T. بمعنى أنه لا يمكنك تحريك المؤشر ولكن يمكنك تغيير القيمة المشار إليها بواسطة المؤشر. أي سوف يعمل *ptr2 = 19 ولكن ptr2++ ; ptr2-- ptr2++ ; ptr2-- الخ لن تعمل. قراءة إلى الخلف: const const إلى نوع T

const T * const ptr3 ; 

مؤشر const إلى نوع بيانات const T. بمعنى أنه لا يمكنك تحريك المؤشر ولا يمكنك تغيير مؤشر نوع البيانات ليكون المؤشر. أي. ptr3-- ; ptr3++ ; *ptr3 = 19; لن يعمل

3) المؤشرات الذكية : { #include <memory> }

المؤشر المشترك :

  T a ; 
     //shared_ptr<T> shptr(new T) ; not recommended but works 
     shared_ptr<T> shptr = make_shared<T>(); // faster + exception safe

     std::cout << shptr.use_count() ; // 1 //  gives the number of " 
things " pointing to it. 
     T * temp = shptr.get(); // gives a pointer to object

     // shared_pointer used like a regular pointer to call member functions
      shptr->memFn();
     (*shptr).memFn(); 

    //
     shptr.reset() ; // frees the object pointed to be the ptr 
     shptr = nullptr ; // frees the object 
     shptr = make_shared<T>() ; // frees the original object and points to new object

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

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

T a ; 
shared_ptr<T> shr = make_shared<T>() ; 
weak_ptr<T> wk = shr ; // initialize a weak_ptr from a shared_ptr 
wk.lock()->memFn() ; // use lock to get a shared_ptr 
//   ^^^ Can lead to exception if the shared ptr has gone out of scope
if(!wk.expired()) wk.lock()->memFn() ;
// Check if shared ptr has gone out of scope before access

انظر: متى يكون std :: weak_ptr مفيد؟

مؤشر فريد: مؤشر خفيف الوزن الذكي مع ملكية حصرية. يستخدم عندما يشير المؤشر إلى كائنات فريدة بدون مشاركة الكائنات بين المؤشرات.

unique_ptr<T> uptr(new T);
uptr->memFn(); 

//T * ptr = uptr.release(); // uptr becomes null and object is pointed to by ptr
uptr.reset() ; // deletes the object pointed to by uptr 

لتغيير الكائن المشار إليه بواسطة ptr الفريد ، استخدم دلالات النقل

unique_ptr<T> uptr1(new T);
unique_ptr<T> uptr2(new T);
uptr2 = std::move(uptr1); 
// object pointed by uptr2 is deleted and 
// object pointed by uptr1 is pointed to by uptr2
// uptr1 becomes null 

اﻟﻣراﺟﻊ: ﯾﻣﻛن أن ﺗﻛون ﻋﻠﻰ اﻷﺳﺎس ﻋﻠﻰ أﻧﮭﺎ ﻣﺛل ﻣؤﺷرات ﺛﺎﺑﺗﺔ ، أي ﻣؤﺷر ﯾﻌﺗﻣد ﻋﻠﻰ اﻟﻛوﻛب وﻻ ﯾﻣﻛن ﻧﻘﻠﮫ ﺑﺻﯾﻐﺔ أﻓﺿل.

انظر: ما هي الاختلافات بين متغير مؤشر ومتغير مرجع في C ++؟

r-value reference : reference to a temporary object   
l-value reference : reference to an object whose address can be obtained
const reference : reference to a data type which is const and cannot be modified 

المرجع: https://www.youtube.com/channel/UCEOGtxYTB6vo6MQ-WQ9W_nQ شكرًا على Andre للإشارة إلى هذا السؤال.


المؤشر الذكي هو كائن يعمل كمؤشر ، ولكنه يوفر أيضًا التحكم في الإنشاء والتدمير والنسخ والتنقل والتخلص من اللقطات.

يمكن للمرء أن ينفذ المؤشر الذكي الخاص به ، ولكن العديد من المكتبات توفر أيضًا تطبيقات مؤشر ذكية لكل منها مزايا وعيوب مختلفة.

على سبيل المثال ، يوفر Boost تطبيقات المؤشر الذكي التالية:

  • shared_ptr<T> هو مؤشر إلى T باستخدام عدد مرجع لتحديد متى لم تعد هناك حاجة إلى الكائن.
  • scoped_ptr<T> هو مؤشر يتم حذفه تلقائيًا عندما يخرج من النطاق. لا الاحالة ممكن.
  • intrusive_ptr<T> هو مؤشر عد مرجع آخر. يوفر أداء أفضل من shared_ptr ، ولكنه يتطلب النوع T لتوفير آلية حساب الإشارة الخاصة به.
  • weak_ptr<T> هو مؤشر ضعيف ، يعمل بالتزامن مع shared_ptr لتجنب المراجع الدائرية.
  • shared_array<T> يشبه shared_ptr ، ولكن للصفائف من T
  • scoped_array<T> تشبه scoped_ptr ، ولكن للصفائف من T

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

بالإضافة إلى ذلك ، توفر المكتبة القياسية C ++ ثلاثة مؤشرات ذكية؛ std::unique_ptr للملكية الفريدة ، std::shared_ptr للملكية المشتركة و std::weak_ptr . std::auto_ptr موجود في C ++ 03 ولكنه مهمل الآن.


أود أن أضيف نقطة أخرى إلى السؤال أعلاه ، فإن std: std :: sharing_ptr الذكي لا يحتوي على مشبِّل منخفض ولا يدعم حسابي ponter ، يمكننا استخدام get () للحصول على مؤشر مدمج.


المؤشر الذكي هو فئة تلتف على مؤشر C ++ "خام" (أو "عاري") ، لإدارة عمر الكائن الذي يتم توجيهه. لا يوجد نوع مؤشر ذكي واحد ، ولكن كلهم ​​يحاولون تجريد المؤشر الخام بطريقة عملية.

ينبغي تفضيل المؤشرات الذكية على مؤشرات الخام. إذا كنت تشعر أنك بحاجة إلى استخدام المؤشرات (فكر أولاً إذا كنت تقوم بذلك فعلاً ) ، فستحتاج عادةً إلى استخدام مؤشر ذكي لأن ذلك يمكن أن يخفف العديد من المشاكل مع المؤشرات الأولية ، وينسى بشكل رئيسي حذف الكائن وتسرب الذاكرة.

مع المؤشرات الأولية ، يجب على المبرمج أن يدمر الكائن بشكل صريح عندما لا يعود مفيدًا.

// Need to create the object to achieve some goal
MyObject* ptr = new MyObject(); 
ptr->DoSomething(); // Use the object in some way
delete ptr; // Destroy the object. Done with it.
// Wait, what if DoSomething() raises an exception...?

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

SomeSmartPtr<MyObject> ptr(new MyObject());
ptr->DoSomething(); // Use the object in some way.

// Destruction of the object happens, depending 
// on the policy the smart pointer class uses.

// Destruction would happen even if DoSomething() 
// raises an exception

تتضمن أبسط سياسة في الاستخدام نطاق كائن مؤشر المؤشر الذكي ، مثل تنفيذها بواسطة boost::scoped_ptr أو std::unique_ptr .

void f()
{
    {
       boost::scoped_ptr<MyObject> ptr(new MyObject());
       ptr->DoSomethingUseful();
    } // boost::scopted_ptr goes out of scope -- 
      // the MyObject is automatically destroyed.

    // ptr->Oops(); // Compile error: "ptr" not defined
                    // since it is no longer in scope.
}

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

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

تتضمن سياسة مؤشر ذكية أكثر تعقيداً مرجع العد المؤشر. هذا لا يسمح بنسخ المؤشر. عند إتلاف "المرجع" الأخير للكائن ، يتم حذف الكائن. يتم تنفيذ هذه السياسة بواسطة boost::shared_ptr و std::shared_ptr .

void f()
{
    typedef std::shared_ptr<MyObject> MyObjectPtr; // nice short alias
    MyObjectPtr p1; // Empty

    {
        MyObjectPtr p2(new MyObject());
        // There is now one "reference" to the created object
        p1 = p2; // Copy the pointer.
        // There are now two references to the object.
    } // p2 is destroyed, leaving one reference to the object.
} // p1 is destroyed, leaving a reference count of zero. 
  // The object is deleted.

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

هناك عيب واحد للإشارة إلى المؤشرات المحسوبة - إمكانية إنشاء مرجع متدلي:

// Create the smart pointer on the heap
MyObjectPtr* pp = new MyObjectPtr(new MyObject())
// Hmm, we forgot to destroy the smart pointer,
// because of that, the object is never destroyed!

الاحتمال الآخر هو إنشاء مراجع دائرية:

struct Owner {
   boost::shared_ptr<Owner> other;
};

boost::shared_ptr<Owner> p1 (new Owner());
boost::shared_ptr<Owner> p2 (new Owner());
p1->other = p2; // p1 references p2
p2->other = p1; // p2 references p1

// Oops, the reference count of of p1 and p2 never goes to zero!
// The objects are never destroyed!

للتغلب على هذه المشكلة ، قام كل من Boost و C ++ 11 بتعريف weak_ptr لتحديد مرجع ضعيف (غير محسوب) إلى shared_ptr .

تحديث

هذه الإجابة قديمة نوعًا ما ، وتصف ما كان "جيدًا" في ذلك الوقت ، وهو عبارة عن مؤشرات ذكية مقدمة من مكتبة Boost. منذ C ++ 11 ، قامت المكتبة القياسية بتوفير أنواع المؤشرات الذكية الكافية ، ولذلك يجب أن تفضل استخدام std::unique_ptr و std::shared_ptr و std::weak_ptr .

يوجد أيضا std::auto_ptr . إنه يشبه إلى حد كبير مؤشر نطاق ، إلا أنه يمتلك أيضًا القدرة الخطيرة "الخاصة" التي يمكن نسخها - والتي تنقل أيضًا الملكية بشكل غير متوقع! تم إيقافه في أحدث المعايير ، لذا لا يجب استخدامه. استخدم std::unique_ptr بدلاً من ذلك.

std::auto_ptr<MyObject> p1 (new MyObject());
std::auto_ptr<MyObject> p2 = p1; // Copy and transfer ownership. 
                                 // p1 gets set to empty!
p2->DoSomething(); // Works.
p1->DoSomething(); // Oh oh. Hopefully raises some NULL pointer exception.

هذا هو الرابط للحصول على إجابات مشابهة: http://sickprogrammersarea.blogspot.in/2014/03/technical-interview-questions-on-c_6.html

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

مثال:

template <class X>
class smart_pointer
{
          public:
               smart_pointer();                          // makes a null pointer
               smart_pointer(const X& x)            // makes pointer to copy of x

               X& operator *( );
               const X& operator*( ) const;
               X* operator->() const;

               smart_pointer(const smart_pointer <X> &);
               const smart_pointer <X> & operator =(const smart_pointer<X>&);
               ~smart_pointer();
          private:
               //...
};

هذه الفئة تطبيق مؤشر ذكية إلى كائن من نوع X. الكائن نفسه موجود على كومة الذاكرة المؤقتة. إليك كيفية استخدامه:

smart_pointer <employee> p= employee("Harris",1333);

مثل مشغلات أخرى ذات حمولة زائدة ، سوف تتصرف p مثل مؤشر عادي ،

cout<<*p;
p->raise_salary(0.5);

"المؤشرات الذكية" هي تلك التي لا داعي للقلق بشأن "إلغاء تخصيص الذاكرة" و "مشاركة الموارد" و "النقل".

يمكنك استخدام هذا المؤشر بشكل جيد بنفس الطريقة التي يعمل بها أي تخصيص في Java. في java Garbage Collector يقوم بالخدعة ، بينما في Smart Pointers ، تتم الحيلة بواسطة Destructors.


http://en.wikipedia.org/wiki/Smart_pointer

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


تستند تحريك الدلالات إلى مراجع rvalue .
الرفض هو كائن مؤقت ، سيتم تدميره في نهاية التعبير. في C ++ الحالي ، ربط rvalues ​​فقط مراجع const . سيسمح C ++ 1x بمراجع rvalue غير const ، وهو عبارة عن T&& مكتوبة بحروف كبيرة ، وهي مراجع لكائنات rvalue.
بما أن الفارق سيفوق في نهاية تعبير ، يمكنك سرقة بياناته . بدلاً من نسخها إلى كائن آخر ، تقوم بنقل بياناتها إليه.

class X {
public: 
  X(X&& rhs) // ctor taking an rvalue reference, so-called move-ctor
    : data_()
  {
     // since 'x' is an rvalue object, we can steal its data
     this->swap(std::move(rhs));
     // this will leave rhs with the empty data
  }
  void swap(X&& rhs);
  // ... 
};

// ...

X f();

X x = f(); // f() returns result as rvalue, so this calls move-ctor

في الكود السابق ، مع compilers القديمة يتم نسخ نتيجة f() إلى x باستخدام مُنشئ النسخة X إذا كان المحول البرمجي الخاص بك يدعم نقل دلالات و X يحتوي على منشئ حركة ، فهذا يسمى بدلاً من ذلك. بما أن حجة rhs الخاصة بها هي عبارة عن rvalue ، فإننا نعلم أنها لم تعد بحاجة إليها ، ويمكننا سرقتها.
لذا يتم نقل القيمة من المؤقت المؤقت الذي لم يتم تسميته من f() إلى x (بينما يتم نقل بيانات x ، التي تم تهيئتها إلى X فارغة ، إلى المؤقت ، والتي سيتم تدميرها بعد التعيين).





c++ pointers c++11 smart-pointers c++-faq