इसका सरल उत्तर यह है कि आपको रवैल्यू रेफरेंस के लिए कोड लिखना चाहिए, जैसे कि आप रेगुलर रेफरेंस कोड चाहते हैं, और आपको समय के समान मानसिक रूप से 99% व्यवहार करना चाहिए। इसमें रिटर्निंग रेफरेंस के बारे में सभी पुराने नियम शामिल हैं (यानी किसी स्थानीय वैरिएबल का संदर्भ कभी नहीं लौटाते)।
जब तक आप एक टेम्प्लेट कंटेनर क्लास नहीं लिख रहे हैं, जिसे std :: फॉरवर्ड का लाभ उठाने की आवश्यकता है और एक जेनेरिक फ़ंक्शन लिखने में सक्षम है जो या तो लेवल्यू या रिवेल्यू रेफरेंस लेता है, यह कमोबेश सही है।
मूव कंस्ट्रक्टर और मूव असाइनमेंट के बड़े फायदों में से एक यह है कि यदि आप उन्हें परिभाषित करते हैं, तो कंपाइलर उनका उपयोग उन मामलों में कर सकते हैं जो आरवीओ (रिटर्न वैल्यू ऑप्टिमाइज़ेशन) और एनआरवीओ (रिटर्न वैल्यू ऑप्टिमाइज़ेशन) नामांकित होने में विफल हैं। कंटेनरों और तारों जैसी महंगी वस्तुओं को कुशलता से मूल्य से लौटाने के लिए यह बहुत बड़ा है।
अब जहां चीजें रूवल संदर्भों के साथ दिलचस्प हो जाती हैं, वह यह है कि आप उन्हें सामान्य कार्यों के तर्क के रूप में भी उपयोग कर सकते हैं। यह आपको उन कंटेनरों को लिखने की अनुमति देता है जिनके पास कॉन्स्ट रेफरेंस (कॉन्स्ट फू और अन्य) और रवैल्यू रेफरेंस (foo && अन्य) दोनों के लिए ओवरलोड हैं। यहां तक कि अगर तर्क भी एक मात्र निर्माता के साथ पारित करने के लिए बहुत बुरा है कॉल यह अभी भी किया जा सकता है:
std::vector vec;
for(int x=0; x<10; ++x)
{
// automatically uses rvalue reference constructor if available
// because MyCheapType is an unamed temporary variable
vec.push_back(MyCheapType(0.f));
}
std::vector vec;
for(int x=0; x<10; ++x)
{
MyExpensiveType temp(1.0, 3.0);
temp.initSomeOtherFields(malloc(5000));
// old way, passed via const reference, expensive copy
vec.push_back(temp);
// new way, passed via rvalue reference, cheap move
// just don't use temp again, not difficult in a loop like this though . . .
vec.push_back(std::move(temp));
}
एसटीएल कंटेनरों को लगभग किसी भी चीज़ के लिए ओवरलोड ले जाने के लिए अपडेट किया गया है (हैश कुंजी और मान, वेक्टर सम्मिलन, आदि), और वह है जहां आप उन्हें सबसे अधिक देखेंगे।
आप उन्हें सामान्य कार्यों के लिए भी उपयोग कर सकते हैं, और यदि आप केवल एक संदर्भ संदर्भ तर्क प्रदान करते हैं, तो आप कॉल करने वाले को ऑब्जेक्ट बनाने और फ़ंक्शन को स्थानांतरित करने के लिए बाध्य कर सकते हैं। यह वास्तव में अच्छे उपयोग की तुलना में एक उदाहरण के रूप में अधिक है, लेकिन मेरे प्रतिपादन पुस्तकालय में, मैंने सभी लोड किए गए संसाधनों को एक स्ट्रिंग सौंपी है, ताकि यह देखना आसान हो कि प्रत्येक ऑब्जेक्ट डीबगर में क्या दर्शाता है। इंटरफ़ेस कुछ इस तरह है:
TextureHandle CreateTexture(int width, int height, ETextureFormat fmt, string&& friendlyName)
{
std::unique_ptr<TextureObject> tex = D3DCreateTexture(width, height, fmt);
tex->friendlyName = std::move(friendlyName);
return tex;
}
यह एक 'टपका हुआ अमूर्त' का एक रूप है, लेकिन मुझे इस तथ्य का लाभ उठाने की अनुमति देता है कि मुझे पहले से ही ज्यादातर समय स्ट्रिंग बनाना था, और अभी तक इसकी एक और प्रतिलिपि बनाने से बचें। यह बिल्कुल उच्च-प्रदर्शन कोड नहीं है, लेकिन संभावनाओं का एक अच्छा उदाहरण है क्योंकि लोगों को इस सुविधा का हैंग हो जाता है। इस कोड को वास्तव में आवश्यकता होती है कि चर या तो कॉल के लिए अस्थायी हो, या std :: Move invoked:
// move from temporary
TextureHandle htex = CreateTexture(128, 128, A8R8G8B8, string("Checkerboard"));
या
// explicit move (not going to use the variable 'str' after the create call)
string str("Checkerboard");
TextureHandle htex = CreateTexture(128, 128, A8R8G8B8, std::move(str));
या
// explicitly make a copy and pass the temporary of the copy down
// since we need to use str again for some reason
string str("Checkerboard");
TextureHandle htex = CreateTexture(128, 128, A8R8G8B8, string(str));
लेकिन यह संकलन नहीं होगा!
string str("Checkerboard");
TextureHandle htex = CreateTexture(128, 128, A8R8G8B8, str);