2014-10-23 30 views
5

के चाल असाइन ऑपरेटर को आमंत्रित करने के लिए std :: move की आवश्यकता क्यों है I C++ 11 सीख रहा हूं और मेरे पास सैमसंग और रावल संदर्भों के बारे में कोई प्रश्न है। मेरे नमूना कोड के रूप में निम्नलिखित (सी ++ शैल यूआरएल cpp.sh/8gt है):std :: vector

#include <iostream> 
#include <vector> 

void aaa(std::vector<int>&& a) 
{ 
    std::cout << "size of a before move: " << a.size() << std::endl; 
    std::vector<int> v; 
    v = a; /*std::move(a)*/ 
    std::cout << "size of a after move: " << a.size() << std::endl; 
} 

int main() 
{ 
    std::vector<int> foo (3,0); 

    aaa(std::move(foo)); 

    return 0; 
} 

का परिणाम है:

size of a before move: 3 
size of a after move: 3 

यह std :: वेक्टर के इस कदम असाइन ऑपरेटर लगता है फंक्शन aaa में v = a लाइन पर नहीं बुलाया जाता है, अन्यथा a के बजाय आकार 0 होगा।
हालांकि अगर मैंबदलता हूंv = std::move(a) के उत्पादन कदम से पहले एक के

आकार बन गया: 3
एक चाल के बाद की का आकार: 0

और मैं एसटीडी की चाल असाइन ऑपरेटर thinke :: वेक्टर यह लागू कर दिया गया है पहर।

मेरा quesiton यही है कि असाइन ऑपरेटर पहली बार क्यों नहीं बुलाया जाता है? सी ++ संदर्भ std :: वेक्टर के अनुसार एक असाइन ऑपरेटर है जो एक रावल्यू संदर्भ लेता है।

प्रतिलिपि (1) वेक्टर & ऑपरेटर = (स्थिरांक वेक्टर & x);
चाल (2) वेक्टर & ऑपरेटर = (वेक्टर & & x);
प्रारंभकर्ता सूची (3) वेक्टर & ऑपरेटर = (प्रारंभकर्ता_सूची आईएल);

फिर v = a पर लाइन के रूप में, जिसे रैवल्यू संदर्भ के रूप में घोषित किया गया है, चालक ऑपरेटर को बुलाया जाना चाहिए। हमें अभी भी std :: move के साथ लपेटने की आवश्यकता क्यों है?

अग्रिम में बहुत धन्यवाद!

[संपादित करें] मुझे लगता है कि लूपुन्रोलर और केरेक एसबी दोनों ने मेरे प्रश्न का उत्तर दिया। धन्यवाद! मुझे नहीं लगता कि मैं दो उत्तरों चुन सकता हूं इसलिए मैं पहले व्यक्ति को चुनूंगा।

+2

एक अभिव्यक्ति संदर्भ * परिवर्तनीय * का संदर्भ देने वाला एक अभिव्यक्ति एक अंतराल है, क्योंकि आप चर कई बार संदर्भित कर सकते हैं। – dyp

+2

क्योंकि "rvalue संदर्भ" एक बुरा और भ्रमित नाम है। और क्योंकि सी ++ खराब और भ्रमित है। –

+1

यह निश्चित रूप से एक अच्छी बात है (एक बुरे और भ्रमित तरीके से)। अन्यथा, 'v = a' चुपचाप' ए 'को संशोधित करेगा, जिससे वास्तव में' auto_ptr'-शैली की अजीबता का कारण बनता है जो सेमेन्टिक्स को स्थानांतरित करने का इरादा रखता था। –

उत्तर

9

से [expr]/6 स्पष्ट हो सकता है इस नोट क्या (जोर मेरा) चल रहा है:

[नोट: कोई व्यंजक एक XValue है अगर यह होता है:

  • फ़ंक्शन को कॉल करने का नतीजा, चाहे वह स्पष्ट रूप से या स्पष्ट रूप से, जिसका रिटर्न टाइप ऑब्जेक्ट प्रकार,
  • ऑब्जेक्ट प्रकार,
  • पर एक रावल संदर्भ के लिए एक कास्ट संदर्भ है
  • एक वर्ग के सदस्य पहुँच अभिव्यक्ति गैर संदर्भ प्रकार का एक गैर स्थैतिक डेटा सदस्य है जिसमें वस्तु अभिव्यक्ति एक XValue है, या
  • एक .* सूचक करने वाली सदस्य अभिव्यक्ति है, जिसमें पहले संकार्य एक XValue है नामित करना और दूसरा ऑपरेंड डेटा सदस्य के लिए एक सूचक है।

सामान्य तौर पर, इस नियम का असर है कि नामित rvalue संदर्भ lvalues ​​ और वस्तुओं XValues ​​रूप में माना जाता करने के लिए अनाम rvalue संदर्भ के रूप में इलाज कर रहे हैं; कार्यों के लिए रैल्यू संदर्भ लाभार्थियों के रूप में माना जाता है या नहीं। - अंत टिप्पणी]

यह देखने के लिए कि अभिव्यक्ति std::move(a) (बुलेट एक) ऊपर दी गई सूची के अनुसार एक XValue है मुश्किल नहीं है।
a एक रैल्यू संदर्भ का नाम है, और इस प्रकार एक अभिव्यक्ति के रूप में एक lvalue है।

6

अभिव्यक्ति a एक लवली है। अभिव्यक्ति std::move(a) एक रैल्यू है। केवल रावल्यू रेवल्यू संदर्भों से जुड़ते हैं, जो चालक को आगे बढ़ाते हैं और असाइनमेंट ऑपरेटर ले जाते हैं।

यह समझने तक अपने आप को दोहराने लायक है: किसी भी संदर्भ चर का मूल्यांकन करना, और किसी भी अव्यवस्थित पॉइंटर को संदर्भित करना, एक लाभा उत्पन्न करता है।

+2

एक महत्वपूर्ण बात यह है कि यह नियम ऐसा क्यों है। जब वह 'ए = वी' का आह्वान करता है, तो कंपाइलर को यह जानने का कोई तरीका नहीं है कि उसे फिर से 'v'' की आवश्यकता नहीं होगी (और वास्तव में, वह बाद में इसका उपयोग करता है), इसलिए जब तक आप इसे विशेष रूप से अधिकृत नहीं करते हैं तब तक यह मान को बदलने का जोखिम नहीं उठा सकता सेवा मेरे। –

+0

@ जेम्ससांज: यह सही है। सुनहरे नियम के रूप में, रावजूदों को अलियाकृत नहीं होने की गारंटी देनी चाहिए। यह भाषा स्तर पर लागू नहीं किया जा सकता है या लागू नहीं किया जा सकता है (जंग जैसे अन्य भाषाएं इसे लागू करती हैं), लेकिन यह होना चाहिए कि कैसे कोई राजस्व के बारे में सोचता है। –

+0

यह याद रखने का एक और तरीका यह है कि एक * रावल्यू संदर्भ * संदर्भ के लिए * बाध्य * क्या हो सकता है: एक रैल्यू। इसका मतलब यह नहीं है कि संदर्भ का उपयोग एक रावल्यू का उपयोग करने जैसा ही है। –

संबंधित मुद्दे