تخطَّ إلى المحتوى

std::move

دلالات النقل std::move

std::move لا تنقل شيئًا فعليًا — تحوّل تعبيرًا إلى rvalue reference، ما يخبر المترجم أنه يمكن «سرقة» موارده الداخلية بدل نسخها.

نسخ كائن كبير مثل std::vector أو std::string تقليديًا يعني حجز ذاكرة جديدة ونسخ كل عنصر — مكلف. move semantics (ميزة C++11) تسمح بدل ذلك بـ«سرقة» المؤشرات الداخلية من الكائن المصدر مباشرة وترك المصدر بحالة فارغة صالحة، بلا أي نسخ فعلي للبيانات — عملية بتكلفة ثابتة (O(1)) بدل تكلفة تتناسب مع الحجم.

std::move نفسها لا تنقل شيئًا — هي فقط cast يحوّل lvalue إلى rvalue reference، فيرشد المترجم لاستخدام move constructor أو move assignment operator بدل النسخة العادية إن كانا متوفرين بالنوع.

الصياغة

Type target = std::move(source);
void func(Type&& rvalueRef);

📄 مثال

std::vector<int> big = {1, 2, 3, 4, 5};
std::vector<int> target = std::move(big);
// target يملك البيانات الآن، big أصبح فارغًا وصالحًا للاستخدام (لكن حالته غير محددة القيمة)

std::cout << target.size(); // 5
std::cout << big.size();    // 0 عادة، لكن لا تعتمد على القيمة الدقيقة

أهم النقاط

العنصرالوظيفة
std::move(x)cast يحوّل x إلى rvalue reference — لا ينقل شيئًا بنفسه
move constructorباني يأخذ Type&& ويسرق موارد المصدر بدل نسخها
move assignmentعامل = يأخذ Type&& لنفس الغرض عند التعيين
rvalue reference (&&)نوع مرجعي جديد بـ C++11 يشير لقيم مؤقتة يمكن «سرقة» مواردها بأمان

💡 نصائح عملية

  • استخدم std::move عندما تنقل ملكية كائن كبير (vector، string) ولن تحتاج القيمة الأصلية بعدها
  • بعد std::move(x)، لا تستخدم x إلا بإعادة تهيئته أولًا — حالته «صالحة لكن غير محددة القيمة»

⚠️ أخطاء شائعة

  • استخدام المتغيّر الأصلي بعد std::move عليه وكأن قيمته ما زالت كما كانت — سلوك خاطئ منطقيًا رغم أنه غالبًا لا يُعطّل البرنامج
  • تطبيق std::move على قيمة سترجعها الدالة (return std::move(local);) — يمنع تحسين المترجم التلقائي (RVO) وغالبًا يبطّئ الكود

خصائص ذات صلة

🎓 تريد فهم الصورة الكاملة خطوة بخطوة؟ ابدأ من مسار CPP الكامل بالعربي.