अंतिम अद्यतन:2026-10-12
C++ std::move का सिद्धांत और उपयोग¶
std::move एक बहुत महत्वपूर्ण फ़ंक्शन है, यह एक ऐसा तरीका प्रदान करता है जिससे एक lvalue ऑब्जेक्ट को एक विशेष प्रकार के rvalue ऑब्जेक्ट, यानी xvalue, के रूप में चिह्नित किया जा सकता है। यह परिवर्तन move semantics के निष्पादन की अनुमति देने के लिए है, न कि सामान्य copy semantics के निष्पादन के लिए।
- std::move का उपयोग क्यों करें
- व्यावहारिक उपयोग के परिदृश्य
1. std::move का उपयोग क्यों करें¶
प्रायः केवल rvalue ऑब्जेक्ट्स पर ही move ऑपरेशन किया जा सकता है, क्योंकि move कंस्ट्रक्टर पैरामीटर के रूप में rvalue reference लेता है, और rvalue reference केवल rvalue से ही बंध सकता है। इसलिए, यदि आप किसी lvalue एक्सप्रेशन द्वारा दर्शाए गए ऑब्जेक्ट पर move ऑपरेशन करना चाहते हैं, तो आपको उसे std::move से xvalue (विशेष rvalue) में बदलने की ज़रूरत है।
std::move का उपयोग सावधानी से करें, क्योंकि move ऑपरेशन ऑब्जेक्ट को ऐसी स्थिति में डाल देता है जिसमें प्रायः केवल उसे नष्ट करने की अनुमति होती है। इसलिए, किसी ऑब्जेक्ट के अंतिम उपयोग पर ही move ऑपरेशन करना सबसे बेहतर है।
std::move वास्तव में move नहीं करता, यह स्पष्ट करना ज़रूरी है कि std::move ऑब्जेक्ट का move ऑपरेशन वास्तव में निष्पादित नहीं करता। यह केवल दिए गए lvalue ऑब्जेक्ट को rvalue reference में बदलता है। नीचे std::move का एक संभावित implementation दिया गया है:
template <typename T>
typename remove_reference<T>::type&& move(T&& t)
{
return static_cast<typename remove_reference<T>::type&&>(t);
}
2. व्यावहारिक उपयोग के परिदृश्य¶
2.1 copy कंस्ट्रक्टर के बजाय move कंस्ट्रक्टर¶
फ़ंक्शन f1 में पैरामीटर a एक rvalue reference वाला lvalue है, rvalue खुद नहीं, क्योंकि इसका एक नाम है। इसलिए, Foo के move कंस्ट्रक्टर को बाध्य करने के लिए हमें इसे rvalue में बदलना होगा, और std::move ठीक यही बखूबी करता है।
struct Foo {
...
Foo(const Foo&) {}
Foo(Foo&&) {}
};
void f1(Foo&& a) {
Foo b(a); // 调用拷贝构造函数,而非移动构造函数
}
void f2(Foo&& a) {
Foo b(std::move(a)); // right
}
2.2 स्वामित्व प्रबंधन¶
मान लीजिए निम्नलिखित कोड है:
उपरोक्त कोड सामान्य रूप से काम करता है, लेकिन आप पॉइंटर की स्वामित्व का निर्धारण नहीं कर सकते। पॉइंटर को कौन delete करेगा? या पॉइंटर को कब delete किया जाना चाहिए? क्या यह कंटेनर नष्ट होने पर delete कर दिया जाएगा?
C++11 में, std::unique_ptr<Foo> p(new Foo()); यह स्टेटमेंट कंपाइल एरर देगा। कारण यह है कि unique ownership नियम लागू हो जाता है।
लेकिन, आप std::move का उपयोग करके पॉइंटर की स्वामित्व स्थानांतरित कर सकते हैं:
अब पॉइंटर की स्वामित्व कंटेनर में स्थानांतरित हो गई है, और कंटेनर के जीवनचक्र के अंत में इसे delete कर दिया जाएगा। यद्यपि ऑब्जेक्ट p अभी भी मौजूद है, लेकिन इसे dereference करने का कोई भी प्रयास null pointer exception उत्पन्न करेगा।
वास्तव में, move ऑपरेशन के बाद, p के पास मौजूद आंतरिक पॉइंटर nullptr पर सेट कर दिया गया है।
कुल मिलाकर, std::move की भूमिका एक ऐसा साधन प्रदान करना है जिससे ऑब्जेक्ट के move semantics को सुरक्षित रूप से लागू किया जा सके, इसके lvalue गुण को rvalue में बदला जा सके, ताकि इसे move कंस्ट्रक्टर या move असाइनमेंट ऑपरेटर द्वारा बुलाया जा सके। std::move का सही उपयोग परफ़ॉर्मेंस बढ़ाता है और स्वामित्व के सही स्थानांतरण को सुनिश्चित करता है।
तो अगला सवाल, std::move का उपयोग कब नहीं करना चाहिए?
संबंधित विषय¶
- C++11 नई विशेषताओं का अवलोकन | C++那些事
- C++ std::bind बनाम lambda तुलना | C++那些事
- C++ वैरिएडिक टेम्प्लेट्स | C++那些事