std::move وstd::forward
حوّل lvalues إلى rvalues باستخدام std::move، وحافظ على فئة القيمة باستخدام std::forward.
std::move وstd::forward درس مجاني في C++ Academy على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C++ Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C++ Academy 4 دروس في المجموع.
قريبتان بوظيفتين مختلفتين
كل من std::move وstd::forward تحويل نوع في وقت الترجمة. تبدوان متشابهتين، لكنهما تحلان مشكلتين مختلفتين.
std::move: تحويل دائم إلى rvalue
يحوّل std::move(x)، دون شروط، x إلى مرجع rvalue. ويمكن للدالة التي تتلقى الكائن بعد ذلك الاستيلاء على موارده.
std::string s = "Hello";
std::string t = std::move(s); // move-constructs t from s
// s is now in a valid-but-unspecified stateمتى تستخدم move؟
استخدم std::move في:
- مُنشئات النقل وعوامل إسناد النقل
- إرجاع متغير محلي عندما تريد فرض النقل (وهو أمر نادر الحاجة — فعادةً ما ينطبق RVO)
- تمرير متغير محلي لم تعد تحتاج إليه إلى دالة تستقبل الكائن للنقل
تنفيذ std::move
إنه في الحقيقة مجرد static_cast متخفٍّ:
template <typename T>
typename std::remove_reference<T>::type&& move(T&& t) noexcept {
return static_cast<typename std::remove_reference<T>::type&&>(t);
}std::forward: الحفاظ على الفئة
في قالب يستخدم مرجع تمرير (T&&)، يحوّل std::forward<T>(x) x إلى فئته الأصلية (lvalue أو rvalue). ويُستخدم للتمرير المثالي.
template <typename T>
void wrapper(T&& arg) {
target(std::forward<T>(arg)); // forwards as lvalue or rvalue depending on T
}لماذا نحتاج إلى التمرير؟
داخل القالب، للوسيط اسم، ما يجعله lvalue حتى إذا مرّر المستدعي rvalue. يستعيد std::forward الفئة الأصلية.
من دون std::forward
من دون forward، سيمرَّر كل وسيط بوصفه lvalue داخل الغلاف، ما يلغي أي دلالات نقل أرادها المستدعي.
template <typename T>
void wrapper(T&& arg) {
target(arg); // always lvalue — wrong
}حدّد دائمًا وسيط القالب لـ forward
يتطلب std::forward<T> وسيط القالب الصريح. ومن دونه سيكون السلوك غير صحيح.
مثال على التمرير المثالي
تحافظ دالة مصنع تمرّر وسائط المُنشئ على التمييز بين rvalue وlvalue لتحقيق الكفاءة.
template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}انقل مرة واحدة
ينبغي نقل كل كائن مرة واحدة كحد أقصى. وبعد النقل، يكون في حالة صالحة لكن غير محددة — وعادةً ما تعيد إسناد قيمة إليه أو تتلفه. وقد يؤدي استخدام كائن نُقلت موارده من دون إعادة إسناد أولًا إلى أخطاء دقيقة.
قواعد عامة
نموذج ذهني سريع:
- لديك نوع محدد وتريد نقله →
std::move - لديك وسيط قالب وتريد الحفاظ على فئته →
std::forward<T>
تحقّق سريعًا
داخل دالة قالب ذات وسيط T&& arg، كيف تمرّر arg مع الحفاظ على فئة lvalue أو rvalue الخاصة به؟
مراجعة
يحوّل std::move النوع دون شروط إلى rvalue، لذا استخدمه مع الكائنات المحددة التي تريد الاستيلاء على مواردها. ويحافظ std::forward<T> على فئة القيمة داخل القوالب العامة، لذا يُستخدم للتمرير المثالي.
الأسئلة الشائعة
هل درس «std::move وstd::forward» مجاني؟
نعم — نص درس «std::move وstd::forward» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C++ Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C++ Academy 4 دروس في المجموع.
ماذا ستتعلم في «std::move وstd::forward»؟
حوّل lvalues إلى rvalues باستخدام std::move، وحافظ على فئة القيمة باستخدام std::forward. تتمرن على C++ Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ C++ Academy؟
لا تُشترط خبرة سابقة. C++ Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «std::move وstd::forward»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس C++ Academy هذا؟
نعم. كل درس في C++ Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- Lvalue مقابل Rvalue: التمييز بينهما
- مراجع Rvalue وصياغة &&
- std::move وstd::forward
- منشئات النقل وإسناد النقل