रूवेल्स, लवल्यूज़, ज़वल्यूज़, ग्लवल्स और प्रील्यूज़ क्या हैं?


1356

C ++ 03 में, एक अभिव्यक्ति या तो एक लकीर है या एक लवल्यू है

C ++ 11 में, एक अभिव्यक्ति एक हो सकती है:

  1. rvalue
  2. lvalue
  3. XValue
  4. glvalue
  5. prvalue

दो श्रेणियां पाँच श्रेणियां बन गई हैं।

  • अभिव्यक्ति की ये नई श्रेणियां क्या हैं?
  • ये नई श्रेणियां मौजूदा प्रतिद्वंद्विता और स्वावलंबी श्रेणियों से कैसे संबंधित हैं?
  • क्या C ++ 0x में रवल और लैवल्यू श्रेणियां वैसी ही हैं जैसी वे C ++ 03 में हैं?
  • इन नई श्रेणियों की आवश्यकता क्यों है? क्या WG21 देवता केवल हमें नश्वर समझने की कोशिश कर रहे हैं?

9
@ पिलिप पॉटर: सी ++ 03 में? हाँ। एक लैवल्यू का उपयोग एक रैवल्यू के रूप में किया जा सकता है क्योंकि एक मानक लैवल्यू-टू-रिवल्यू रूपांतरण है।
जेम्स मैकनेलिस

14
@ टायलर: "यदि आप इसे असाइन कर सकते हैं, तो यह एक अंतराल है, अन्यथा, यह एक प्रतिद्वंद्विता है।" -> गलत, आप वर्ग के rvalues ​​को असाइन कर सकते हैं string("hello") = string("world"):।
fredoverflow

4
ध्यान दें कि यह मूल्य श्रेणी है। अधिक गुण हैं जो भाव हो सकते हैं। इनमें बिट-फील्ड (सत्य / असत्य), अस्थायी (सत्य / असत्य) और प्रकार (इसके प्रकार) शामिल हैं।
जोहान्स शाउब -

30
मुझे लगता है कि ऊपर दिए गए फ्रेड का लिंक यहां के किसी भी उत्तर से बेहतर है। लिंक मृत है, यद्यपि। इसे स्थानांतरित कर दिया गया: stroustrup.com/terminology.pdf
आर। मार्टिनो फर्नांडिस

74
C ++ में भी आपके प्रकार के प्रकार हैं
nielsbot

जवाबों:


634

मुझे लगता है कि यह दस्तावेज़ इतना संक्षिप्त परिचय नहीं दे सकता है: n3055

पूरे हत्याकांड की शुरुआत मूवमेंट शब्दार्थ से हुई। एक बार जब हमारे पास ऐसे भाव होते हैं जिन्हें स्थानांतरित नहीं किया जा सकता है और कॉपी नहीं किया जाता है, तो अचानक से नियमों को समझना आसान हो जाता है, जो कि स्थानांतरित किए जा सकने वाले भावों के बीच अंतर और किस दिशा में हैं।

ड्राफ्ट के आधार पर मैं जो अनुमान लगाता हूं, उससे r / l मूल्य का अंतर समान रहता है, केवल चलती चीजों के संदर्भ में गड़बड़ हो जाती है।

क्या उनकी जरूरत है? शायद नहीं अगर हम नई सुविधाओं को त्यागना चाहते हैं। लेकिन बेहतर अनुकूलन की अनुमति देने के लिए हमें शायद उन्हें गले लगाना चाहिए।

का हवाला देते हुए n3055 :

  • एक लेवल्यू (तथाकथित, ऐतिहासिक रूप से, क्योंकि लेवेल्यू एक असाइनमेंट अभिव्यक्ति के बाईं ओर दिखाई दे सकता है) एक फ़ंक्शन या ऑब्जेक्ट को नामित करता है। [उदाहरण: यदि Eसूचक प्रकार की अभिव्यक्ति है, तो *E वस्तु या फ़ंक्शन को E इंगित करने वाले बिंदुओं की ओर संकेत करता है । एक अन्य उदाहरण के रूप में, एक फ़ंक्शन को कॉल करने का परिणाम जिसका वापसी प्रकार एक लैवल्यू संदर्भ है, एक अंतराल है।]
  • एक xvalue ("ईएक्सपायरिंग" मूल्य) भी एक वस्तु को संदर्भित करता है, आमतौर पर अपने जीवनकाल के अंत में (ताकि इसके संसाधनों को ले जाया जा सके, उदाहरण के लिए)। एक xvalue कुछ विशेष प्रकार के भावों का परिणाम है, जिसमें rvalue संदर्भ शामिल हैं। [उदाहरण: एक फ़ंक्शन को कॉल करने का परिणाम जिसका वापसी प्रकार एक रैवल्यू संदर्भ है, एक xvalue है।]
  • एक glvalue ( "सामान्यीकरण" lvalue) एक है lvalue या एक XValue
  • एक rvalue (तथाकथित, ऐतिहासिक रूप से, क्योंकि rvalues ​​एक असाइनमेंट अभिव्यक्ति के दाईं ओर दिखाई दे सकता है) एक xvalue, एक अस्थायी ऑब्जेक्ट या उसके उप-विषय है, या एक मूल्य जो किसी ऑब्जेक्ट से जुड़ा नहीं है।
  • एक प्रचलन ("शुद्ध" अवतरण ) एक प्रचलन है जो एक xvalue नहीं है। [उदाहरण: एक फ़ंक्शन को कॉल करने का परिणाम जिसका रिटर्न प्रकार एक संदर्भ नहीं है एक प्रचलन है]

प्रश्न में दस्तावेज़ इस प्रश्न के लिए एक महान संदर्भ है, क्योंकि यह मानक में सटीक बदलाव दिखाता है जो नए नामकरण की शुरूआत के परिणामस्वरूप हुआ है।


धन्यवाद, यह उत्तर वास्तव में उपयोगी है! लेकिन मेरे संकलक xvalues ​​और prvalues ​​के लिए आपके उदाहरणों से सहमत नहीं हैं; वे इसके ठीक विपरीत हैं। रैवल्यू संदर्भ द्वारा लौटने से मुझे एक प्रचलन मिलता है, और मूल्य द्वारा वापस आना मुझे एक xvalue देता है। क्या आपने उन्हें मिलाया, या मेरा परीक्षण बिस्तर टूट गया है? मैंने GCC 4.6.1, क्वांज़ (svn से) और MSVC के साथ यह कोशिश की, और वे सभी एक ही व्यवहार दिखाते हैं।
किम ग्रासमैन

उफ़, मैंने केवल लिंक का अनुसरण किया और देखा कि उदाहरण स्रोत में हैं। मैं मानक की मेरी प्रति
ढूंढता हूँ और जाँचता हूँ

4
मैं विभिन्न अभिव्यक्तियों का परीक्षण करने के लिए यहां से मैक्रोज़ का उपयोग करता हूं: stackoverflow.com/a/6114546/96963 यह हो सकता है कि वे चीजों को गलत बताते हैं।
किम ग्रासमैन

1
Xvalue जोड़ना चाल शब्दार्थ के लिए नहीं है। केवल लैवल्यू और रेवल्यू, मूव सिमेंटिक्स, परफेक्ट फॉरवर्ड और रिवेल्यू रेफरेंस दोनों ही अभी भी अच्छी तरह से काम कर रहे हैं। मुझे लगता है कि xvalue सिर्फ डिक्लेयर ऑपरेटर के लिए है: यदि ऑपरेंड एक्सप्रेशन xvalue है, तो डिक्लेप्ट टाइप rvalue रेफरेंस देता है।
ligand

1
@MuhamedCicak "हर अभिव्यक्ति या तो एक लवलीन या एक भाव है": यह सच है; और मानक (या दस्तावेज़ n3055) यह झूठ नहीं कहता है। इस वाक्य को पार करने का कारण यह है कि आप दस्तावेज़ के दो संस्करणों के बीच बदलाव देख रहे थे। सजा को हटा दिया गया था क्योंकि अधिक सटीक स्पष्टीकरण जोड़े जाने के बाद यह अधूरा हो गया था।
अधिकतम

337

अभिव्यक्ति की ये नई श्रेणियां क्या हैं?

FCD (n3092) एक उत्कृष्ट विवरण नहीं है:

- एक लैवल्यू (तथाकथित रूप से, ऐतिहासिक रूप से, क्योंकि लेवेल्यू बायीं ओर एक असाइनमेंट एक्सप्रेशन के रूप में दिखाई दे सकता है) एक फ़ंक्शन या ऑब्जेक्ट को नामित करता है। [उदाहरण: यदि E पॉइंटर प्रकार की अभिव्यक्ति है, तो * E एक लैवल्यू एक्सप्रेशन है, जो उस ऑब्जेक्ट या फ़ंक्शन को संदर्भित करता है, जिसमें E इंगित करता है। एक अन्य उदाहरण के रूप में, एक फ़ंक्शन को कॉल करने का परिणाम जिसका वापसी प्रकार एक लैवल्यू संदर्भ है एक लैवल्यू है। उदाहरण का]

- एक xvalue (एक "eXpiring" मूल्य) भी एक वस्तु को संदर्भित करता है, आमतौर पर अपने जीवनकाल के अंत के पास (ताकि इसके संसाधनों को ले जाया जा सके, उदाहरण के लिए)। एक xvalue कुछ विशेष प्रकार के भावों का परिणाम है, जिसमें rvalue सन्दर्भ (8.3.2) शामिल हैं। [उदाहरण: एक फ़ंक्शन को कॉल करने का परिणाम जिसका वापसी प्रकार एक रैवल्यू संदर्भ है, एक xvalue है। उदाहरण का]

- एक चमक ("सामान्यीकृत" अंतराल) एक अंतराल या एक xvalue है।

- एक प्रतिद्वंद्विता (तथाकथित रूप से, ऐतिहासिक रूप से, क्योंकि एक असाइनमेंट अभिव्यक्तियों के दाहिनी ओर स्थित rvalues ​​दिखाई दे सकती है) एक xvalue, एक अस्थायी वस्तु (12.2) या उसके अधीन सबऑब्जेक्ट है, या एक मूल्य जो किसी वस्तु से जुड़ा नहीं है।

- एक प्रचलन ("शुद्ध" अवतरण) एक प्रचलन है जो एक xvalue नहीं है। [उदाहरण: एक फ़ंक्शन को कॉल करने का परिणाम जिसका वापसी प्रकार एक संदर्भ नहीं है एक प्रचलन है। शाब्दिक का मान जैसे कि १२, of.३e5, या सच भी एक प्रचलन है। उदाहरण का]

हर अभिव्यक्ति इस वर्गीकरण में मौलिक वर्गीकरणों में से एक है: लवल्यू, ज़वल्यू, या प्रील्यूव। किसी अभिव्यक्ति की इस संपत्ति को उसकी मूल्य श्रेणी कहा जाता है। [नोट: क्लॉज 5 में प्रत्येक बिल्ट-इन ऑपरेटर की चर्चा उस मूल्य की श्रेणी को इंगित करती है, जो इसकी पैदावार की मात्रा और ऑपरेंड की मूल्य श्रेणियों की अपेक्षा करता है। उदाहरण के लिए, बिल्ट-इन असाइनमेंट ऑपरेटर्स को उम्मीद है कि लेफ्ट ऑपरेंड एक लैवल्यू है और राइट ऑपरैंड प्रील्यूव है और परिणाम के रूप में एक लैवल्यू है। उपयोगकर्ता-परिभाषित ऑपरेटर फ़ंक्शंस हैं, और उनके द्वारा अपेक्षित मानों की श्रेणी और उपज उनके पैरामीटर और रिटर्न प्रकारों द्वारा निर्धारित की जाती हैं। ध्यान दें

मेरा सुझाव है कि आप पूरे खंड को 3.10 अंतराल और फिर से पढ़ें

ये नई श्रेणियां मौजूदा प्रतिद्वंद्विता और लवल्यू श्रेणियों से कैसे संबंधित हैं?

फिर:

वर्गीकरण

क्या C ++ 0x में रवल और लैवल्यू श्रेणियां वैसी ही हैं जैसी वे C ++ 03 में हैं?

विशेष रूप से चाल शब्दार्थों की शुरुआत के साथ प्रतिद्वंद्वियों के शब्दार्थ विकसित हुए हैं।

इन नई श्रेणियों की आवश्यकता क्यों है?

ताकि चाल निर्माण / असाइनमेंट को परिभाषित और समर्थन किया जा सके।


54
मुझे यहां का डायग्राम पसंद है। मुझे लगता है कि "हर अभिव्यक्ति इस वर्गीकरण में मौलिक वर्गीकरणों में से एक: लैवल्यू, ज़वल्यू, या प्रील्यूव से संबंधित है।" फिर उन तीन मूल वर्गों को दिखाने के लिए आरेख का उपयोग करना आसान है, जो चमक और लय बनाने के लिए संयुक्त हैं।
एरॉन मैकडैड

2
"ग्लव्यू" "प्रोल्यूव नहीं है" के बराबर है, और "रिवैल्यू" "लैवल्यू नहीं है" के बराबर है।
व्लादिमीर रेशेतनिकोव

2
इसने मेरी सबसे अधिक मदद की: bajamircea.github.io/assets/2016-04-07-move-forward/… (मूल्य श्रेणियों का वेन आरेख)
जॉन पी

1
@AaronMcDaid हाय, त्वरित प्रश्न यदि आप / कोई जवाब कर सकते हैं ... क्यों नाम नहीं glvalueके रूप में lvalueऔर lvalueके रूप में plvalue, एक समान होना चाहिए?
विजय चावड़ा

184

मैं आपके अंतिम प्रश्न से शुरू करूंगा:

इन नई श्रेणियों की आवश्यकता क्यों है?

C ++ मानक में कई नियम होते हैं जो एक अभिव्यक्ति के मूल्य श्रेणी से निपटते हैं। कुछ नियम अंतराल और अंतराल के बीच अंतर करते हैं। उदाहरण के लिए, जब यह अधिभार संकल्प की बात आती है। अन्य नियम चमक और प्रचलन के बीच एक अंतर करते हैं। उदाहरण के लिए, आपके पास अधूरा या सार प्रकार के साथ एक चमक हो सकती है लेकिन अपूर्ण या सार प्रकार के साथ कोई प्रस्ताव नहीं है। इससे पहले कि हमारे पास यह शब्दावली थी कि नियमों को वास्तव में ग्लव्यू / प्रचलन के बीच अंतर करने की आवश्यकता होती है, जिसे lvalue / rvalue के रूप में संदर्भित किया जाता है और वे या तो अनजाने में गलत थे या नियम के लिए बहुत सारे स्पष्टीकरण और अपवाद शामिल थे "ला ... जब तक कि नामावली के कारण नहीं होता है। संदर्भ संदर्भ ... "। तो, यह एक अच्छा विचार की तरह लगता है कि सिर्फ गौरव की अवधारणाएं दें और अपने स्वयं के नाम को प्रचलित करें।

अभिव्यक्ति की ये नई श्रेणियां क्या हैं? ये नई श्रेणियां मौजूदा प्रतिद्वंद्विता और लवल्यू श्रेणियों से कैसे संबंधित हैं?

हमारे पास अभी भी नियम और अंतराल हैं जो C ++ 98 के साथ संगत हैं। हमने केवल दो उपसमूहों, xvalues ​​और prvalues ​​में rvalues ​​को विभाजित किया है, और हम lvalues ​​और xvalues ​​को glvalues ​​के रूप में संदर्भित करते हैं। अनाम अंतराल संदर्भों के लिए Xvalues ​​एक नए प्रकार का मान श्रेणी है। हर अभिव्यक्ति इन तीनों में से एक है: लवल्यू, ज़वल्यू, प्रवल्यू। एक वेन आरेख इस तरह दिखेगा:

    ______ ______
   /      X      \
  /      / \      \
 |   l  | x |  pr  |
  \      \ /      /
   \______X______/
       gl    r

कार्यों के उदाहरण:

int   prvalue();
int&  lvalue();
int&& xvalue();

लेकिन यह भी मत भूलना कि नामांकित संदर्भ संदर्भ हैं:

void foo(int&& t) {
  // t is initialized with an rvalue expression
  // but is actually an lvalue expression itself
}

165

इन नई श्रेणियों की आवश्यकता क्यों है? क्या WG21 देवता केवल हमें नश्वर समझने की कोशिश कर रहे हैं?

मुझे नहीं लगता कि अन्य उत्तर (हालांकि उनमें से कई अच्छे हैं) वास्तव में इस विशेष प्रश्न के उत्तर पर कब्जा कर लेते हैं। हां, ये श्रेणियां और इस तरह के शब्दार्थ को स्थानांतरित करने की अनुमति देते हैं, लेकिन जटिलता एक कारण से मौजूद है। यह C ++ 11 में सामान ले जाने का एक अदृश्य नियम है:

जब आप निर्विवाद रूप से ऐसा करने के लिए सुरक्षित हैं, तब ही चले जाएँगे।

यही कारण है कि ये श्रेणियां मौजूद हैं: उन मूल्यों के बारे में बात करने में सक्षम होने के लिए जहां यह उनसे स्थानांतरित करने के लिए सुरक्षित है, और उन मूल्यों के बारे में बात करने के लिए जहां यह नहीं है।

आर-मूल्य संदर्भों के शुरुआती संस्करण में, आंदोलन आसानी से हुआ। बहुत आसानी से। आसानी से पर्याप्त है कि जब उपयोगकर्ता वास्तव में मतलब नहीं था, तो अंतर्निहित रूप से चलती चीजों के लिए बहुत अधिक संभावनाएं थीं।

यहां ऐसी परिस्थितियां हैं जिनके तहत कुछ स्थानांतरित करना सुरक्षित है:

  1. जब यह एक अस्थायी या उसके अधीन है। (Prvalue)
  2. जब उपयोगकर्ता ने स्पष्ट रूप से इसे स्थानांतरित करने के लिए कहा है

अगर तुम यह करते हो:

SomeType &&Func() { ... }

SomeType &&val = Func();
SomeType otherVal{val};

यह क्या करता है? कल्पना के पुराने संस्करणों में, 5 मान आने से पहले, यह एक चाल को भड़काएगा। बिलकुल यह करता है। आपने कंस्ट्रक्टर के लिए एक रेवल्यू रेफ़रेंस पास किया, और इस तरह यह उस कंस्ट्रक्टर को बाँध देता है जो रिवैल्यू रेफ़रेंस लेता है। ज़ाहिर सी बात है।

इसके साथ सिर्फ एक समस्या है; आपने इसे स्थानांतरित करने के लिए नहीं कहा । ओह, आप कह सकते हैं कि &&एक सुराग होना चाहिए था, लेकिन यह इस तथ्य को नहीं बदलता है कि इसने नियम को तोड़ा। valअस्थायी नहीं है क्योंकि अस्थायी लोगों के नाम नहीं हैं। आपने अस्थायी जीवनकाल बढ़ाया हो सकता है, लेकिन इसका मतलब है कि यह अस्थायी नहीं है ; यह किसी भी अन्य स्टैक चर की तरह है।

यदि यह अस्थायी नहीं है, और आपने इसे स्थानांतरित करने के लिए नहीं कहा है, तो चलना गलत है।

स्पष्ट समाधान valएक अंतराल बनाना है । इसका मतलब है कि आप इससे आगे नहीं बढ़ सकते। अच्छी बात है; इसे नाम दिया गया है, इसलिए इसका एक अंतराल है।

एक बार जब आप ऐसा कर लेते हैं, तो आप यह नहीं कह सकते कि SomeType&&इसका मतलब वही है जो कभी भी होता है। आपने अब नामांकित संदर्भों और अनाम नामांकित संदर्भों के बीच अंतर किया है। खैर, नामांकित संदर्भ संदर्भों के अंतराल हैं; यह हमारे ऊपर समाधान था। तो हम अनाम असमान संदर्भ ( Funcऊपर से वापसी मूल्य ) को क्या कहते हैं?

यह एक अंतराल नहीं है, क्योंकि आप एक अंतराल से नहीं जा सकते। और हमें एक वापसी करके स्थानांतरित करने में सक्षम होने की आवश्यकता है &&; कुछ और स्थानांतरित करने के लिए आप स्पष्ट रूप से कैसे कह सकते हैं? जो है std::move, सब के बाद लौटता है। यह एक प्रतिद्वंद्विता (पुरानी शैली) नहीं है, क्योंकि यह एक समीकरण के बाईं ओर हो सकता है (चीजें वास्तव में थोड़ी अधिक जटिल हैं, इस प्रश्न और नीचे की टिप्पणियों को देखें)। यह न तो एक लवलीन है और न ही एक लकीर; यह एक नई तरह की बात है।

हमारे पास एक ऐसा मूल्य है जिसे आप एक लवल्यू के रूप में मान सकते हैं, सिवाय इसके कि यह अनुमानित रूप से जंगम है। हम इसे एक xvalue कहते हैं।

ध्यान दें कि xvalues ​​वे हैं जो हमें अन्य दो श्रेणियों के मान प्राप्त करते हैं:

  • एक प्रचलन वास्तव में पिछले प्रकार के प्रचलन के लिए सिर्फ नया नाम है, अर्थात वे वे प्रचलन हैं जो कि एक्सवल्स नहीं हैं

  • Glvalues ​​एक समूह में xvalues ​​और lvalues ​​का मिलन है, क्योंकि वे बहुत सारे गुणों को साझा करते हैं।

तो वास्तव में, यह सब xvalues ​​पर आता है और आंदोलन को केवल और केवल कुछ स्थानों तक सीमित करने की आवश्यकता है। उन स्थानों को व्याप्त श्रेणी द्वारा परिभाषित किया गया है; प्रिवल्यूज़ निहित चाल हैं, और std::movexvalues स्पष्ट चालें हैं ( एक xvalue लौटाता है)।


11
@ थोमस: यह एक उदाहरण है; इससे कोई फर्क नहीं पड़ता कि यह रिटर्न वैल्यू कैसे बनाता है। क्या मायने रखती है कि यह एक रिटर्न है &&
निकोल बोलस

1
ध्यान दें: किसी समीकरण के बाएं-किनारे पर प्रील्यूस हो सकते हैं, साथ ही - जैसे X foo(); foo() = X;... इस मूलभूत कारण से, मैं उपरोक्त उत्कृष्ट उत्तर का अंत तक अनुसरण नहीं कर सकता, क्योंकि आप वास्तव में केवल भेद करते हैं नए xvalue, और पुराने शैली का प्रचलन, इस तथ्य के आधार पर कि यह lhs पर हो सकता है।
डैन निसेनबाम

1
Xएक वर्ग होने के नाते; X foo();एक फ़ंक्शन घोषणा और foo() = X();कोड की एक पंक्ति होने के नाते। (मैंने foo() = X();अपनी उपरोक्त टिप्पणी में कोष्ठकों के दूसरे सेट को छोड़ दिया ।) एक प्रश्न के लिए, जिसे मैंने अभी-अभी इस उपयोग के साथ पोस्ट किया है, देखें stackoverflow.com/questions/15482508/…
Dan Nissenbaum

1
@DanNissenbaum "xvalue असाइनमेंट एक्सप्रेशन के बाईं ओर नहीं हो सकता" - क्यों नहीं? देखें ideone.com/wyrxiT
मिखाइल

1
ज्ञानवर्धक उत्तर। यह निस्संदेह यहाँ सबसे अच्छा जवाब है। इसने मुझे नई मूल्य श्रेणियों को पेश करने का औचित्य दिया और पहले क्या हुआ।
निकोस

136

IMHO, इसके अर्थ के बारे में सबसे अच्छी व्याख्या ने हमें Stroustrup + को DANiel Sándor और Mohan के उदाहरणों पर ध्यान दिया :

Stroustrup:

अब मैं गंभीर रूप से चिंतित था। स्पष्ट रूप से हम एक गतिरोध या एक गड़बड़ या दोनों के लिए नेतृत्व कर रहे थे। मैंने लंचटाइम एक विश्लेषण करने में बिताया कि कौन से गुण (मूल्य) स्वतंत्र थे। केवल दो स्वतंत्र गुण थे:

  • has identity - यानी और पता, एक सूचक, उपयोगकर्ता यह निर्धारित कर सकता है कि क्या दो प्रतियां समान हैं, आदि।
  • can be moved from - अर्थात हमें कुछ अनिश्चित, लेकिन मान्य स्थिति में "कॉपी" के स्रोत को छोड़ने की अनुमति है

इसने मुझे इस निष्कर्ष पर पहुँचाया कि वास्तव में तीन प्रकार के मूल्य हैं (ऋणात्मक संकेत देने के लिए एक बड़े अक्षर का उपयोग करने के रेगेक्स नोटिकल ट्रिक का उपयोग करके - मैं जल्दी में था):

  • iM: की पहचान है और इससे स्थानांतरित नहीं किया जा सकता है
  • im: की पहचान है और इससे स्थानांतरित किया जा सकता है (उदाहरण के लिए एक अंतराल संदर्भ के लिए एक कास्टिंग कास्टिंग का परिणाम)
  • Im: पहचान नहीं है और से स्थानांतरित किया जा सकता है।

    चौथी संभावना, IM(पहचान नहीं है और इसे स्थानांतरित नहीं किया जा सकता C++है) किसी अन्य भाषा में (या, मुझे नहीं लगता) उपयोगी नहीं है ।

मूल्यों के इन तीन मौलिक वर्गीकरणों के अलावा, हमारे पास दो स्पष्ट सामान्यीकरण हैं जो दो स्वतंत्र गुणों के अनुरूप हैं:

  • i: पहचान है
  • m: से ले जाया जा सकता है

इससे मुझे इस चित्र को बोर्ड पर लाना पड़ा: यहां छवि विवरण दर्ज करें

नामकरण

मैंने देखा कि हम केवल नाम करने की स्वतंत्रता पर था: बाएं (लेबल करने के लिए दो अंक iMऔर iअधिक या कम औपचारिकता के साथ लोगों को क्या कहा जाता है) lvaluesऔर सही (लेबल पर दो अंक mऔर Im) कर रहे हैं क्या और अधिक या कम औपचारिकता के साथ लोगों को बुलाया है rvalues। यह हमारे नामकरण में परिलक्षित होना चाहिए। यही है, के बाएं "पैर" से Wसंबंधित नाम होना चाहिए lvalueऔर दाईं ओर के "पैर" में Wनाम से संबंधित होना चाहिए rvalue.I ध्यान दें कि यह पूरी चर्चा / समस्या प्रतिद्वंद्वियों के संदर्भों की शुरूआत से उत्पन्न होती है और शब्दार्थ को आगे बढ़ाती है। ये धारणा बस स्ट्रेची की दुनिया में मौजूद नहीं है, जिसमें सिर्फ rvaluesऔर सिर्फ शामिल हैं lvalues। किसी ने देखा कि जो विचार हैं

  • हर valueएक lvalueया एक हैrvalue
  • एक lvalueएक नहीं है rvalueऔर एक rvalueनहीं हैlvalue

हमारी चेतना में बहुत गहराई से अंतर्निहित हैं, बहुत उपयोगी गुण हैं, और इस dichotomy के निशान ड्राफ्ट मानक पर पाए जा सकते हैं। हम सभी सहमत थे कि हमें उन गुणों को संरक्षित करना चाहिए (और उन्हें सटीक बनाना चाहिए)। इसने हमारे नामकरण विकल्पों को और विवश कर दिया। मैंने देखा कि मानक पुस्तकालय शब्द का rvalueअर्थ m(सामान्यीकरण) करने के लिए उपयोग करता है , ताकि मानक पुस्तकालय की अपेक्षा और पाठ को संरक्षित करने के लिए दाहिने हाथ के निचले बिंदु का Wनाम होना चाहिए rvalue.

इससे नामकरण की एक केंद्रित चर्चा हुई। सबसे पहले, हमें यह तय करने की आवश्यकता है कि इसका मतलब या सामान्यीकरण lvalue.होना चाहिए ? डौग ग्रेगोर के नेतृत्व में, हमने मुख्य भाषा में उन जगहों को सूचीबद्ध किया जहां शब्द एक या दूसरे का अर्थ करने के लिए योग्य था। एक सूची बनाई गई थी और ज्यादातर मामलों में और सबसे पेचीदा / भंगुर पाठ का वर्तमान में अर्थ है । यह अंतराल का शास्त्रीय अर्थ है क्योंकि "पुराने दिनों में" कुछ भी नहीं स्थानांतरित किया गया था; में एक उपन्यास धारणा है । इसके अलावा, टॉपलेट प्वाइंट का नामकरण हमें संपत्ति देता है कि हर मूल्य एक या एक है , लेकिन दोनों नहीं।lvalueiMilvaluelvalueiMmoveC++0xW lvaluelvaluervalue

तो, शीर्ष बाएं बिंदु Wहै lvalueऔर नीचे दाईं ओर बिंदु वह rvalue.है जो नीचे बाएं और शीर्ष दाएं बिंदु बनाता है? नीचे के बाएं बिंदु को शास्त्रीय अंतराल का एक सामान्यीकरण है, जो चाल के लिए अनुमति देता है। तो यह एक generalized lvalue.नाम है हम इसे glvalue.संक्षिप्त नाम के बारे में समझा सकते हैं, लेकिन (मुझे लगता है) तर्क के साथ नहीं। हमने मान लिया था कि गंभीर उपयोग में generalized lvalue किसी भी तरह संक्षिप्त किया जाएगा, इसलिए हमने इसे तुरंत (या जोखिम भ्रम) बेहतर किया। डब्ल्यू का शीर्ष दाहिना बिंदु नीचे के दाईं ओर से कम सामान्य है (अब, जैसा कि कभी भी, कहा जाता है rvalue)। वह बिंदु एक वस्तु की मूल शुद्ध धारणा का प्रतिनिधित्व करता है जिसे आप स्थानांतरित कर सकते हैं क्योंकि इसे फिर से संदर्भित नहीं किया जा सकता है (एक विध्वंसक को छोड़कर)। मैं वाक्यांश पसंद आया specialized rvalueके विपरीत generalized lvalueलेकिनpure rvalueसंक्षिप्त रूप से prvalueजीतने के लिए (और शायद ठीक ही ऐसा है)। तो, डब्ल्यू का बायां पैर है lvalueऔर glvalueदायां पैर है prvalueऔर rvalue.संयोग से, हर मूल्य या तो एक चमक या एक प्रचलन है, लेकिन दोनों नहीं।

यह पत्ते के शीर्ष बीच W: im; वह है, ऐसे मूल्य जिनकी पहचान है और उन्हें स्थानांतरित किया जा सकता है। हमारे पास वास्तव में कुछ भी नहीं है जो हमें उन गूढ़ जानवरों के लिए एक अच्छे नाम के लिए मार्गदर्शन करता है। वे (ड्राफ्ट) मानक पाठ के साथ काम करने वाले लोगों के लिए महत्वपूर्ण हैं, लेकिन एक घरेलू नाम बनने की संभावना नहीं है। हमें मार्गदर्शन करने के लिए नामकरण पर कोई वास्तविक अड़चन नहीं आई, इसलिए हमने केंद्र के लिए 'x' उठाया, अज्ञात, अजीब, केवल xpert, या यहां तक ​​कि एक्स-रेटेड।

स्टीव अंतिम उत्पाद दिखा रहा है


14
हाँ, यह मानक प्रस्तावों की तुलना में सी ++ कॉमाइट के मूल प्रस्तावों और चर्चाओं को पढ़ने के लिए बेहतर है, यदि आप समझना चाहते हैं कि उनका क्या मतलब है: डी
इवान कुश

8
साहित्य में पहचान नहीं होती है और उसे इससे दूर नहीं किया जा सकता है; वे फिर भी उपयोगी हैं।
DrPizza

मैं सिर्फ एक बात स्पष्ट करना चाहता हूं। int && f () {वापसी 1; } और MyClass && g () {वापसी MyClass (); } xvalue लौटाएं, है ना? फिर मैं अभिव्यक्ति की पहचान कहां पा सकता हूं च (); और "जी ()?" उनकी पहचान है, क्योंकि रिटर्न स्टेटमेंट में एक और अभिव्यक्ति है, जो उसी वस्तु को संदर्भित करता है जैसे वे करते हैं - क्या मैं इसे सही समझता हूं?
डैनियल सांडोर

6
@DrPizza मानक के अनुसार: स्ट्रिंग शाब्दिक हैं lvalue, अन्य सभी शाब्दिक हैं prvalue। कड़ाई से बोलते हुए आप कह सकते हैं कि गैर-स्ट्रिंग शाब्दिक के लिए एक तर्क अचल होना चाहिए, लेकिन यह नहीं है कि मानक कैसे लिखा जाता है।
ब्रायन वंडेनबर्ग

59

परिचय

ISOC ++ 11 (आधिकारिक तौर पर ISO / IEC 14882: 2011) C ++ प्रोग्रामिंग भाषा के मानक का सबसे हाल का संस्करण है। उदाहरण के लिए, इसमें कुछ नई सुविधाएँ और अवधारणाएँ शामिल हैं:

  • संदर्भों को देखें
  • xvalue, glvalue, prvalue अभिव्यक्ति मूल्य श्रेणियां
  • शब्दार्थ चाल

यदि हम नई अभिव्यक्ति मूल्य श्रेणियों की अवधारणाओं को समझना चाहते हैं, तो हमें इस बात से अवगत होना होगा कि वहाँ व्याप्तता और अंतराल के संदर्भ हैं। यह जानना बेहतर है कि प्रतिद्वंद्वियों को नॉन-कास्ट रैवल्यू संदर्भों में पारित किया जा सकता है।

int& r_i=7; // compile error
int&& rr_i=7; // OK

अगर हम वर्किंग ड्राफ्ट N3337 (प्रकाशित ISOC ++ 11 मानक के लिए सबसे समान ड्राफ्ट) से लेवेल्यूज़ और रिवैल्यूज़ शीर्षक वाली उपधारा को उद्धृत करते हैं, तो हम मूल्य श्रेणियों की अवधारणाओं का कुछ अंतर्ज्ञान प्राप्त कर सकते हैं।

३.१० अंतराल और अंतराल [बेसिक.लव]

1 चित्र 1 में वर्गीकरण के अनुसार वर्गीकृत किया गया है।

  • एक लवल्यू (तथाकथित रूप से, ऐतिहासिक रूप से, क्योंकि लेवेल्यू बायीं ओर एक असाइनमेंट एक्सप्रेशन के रूप में प्रकट हो सकता है) एक फ़ंक्शन या ऑब्जेक्ट को नामित करता है। [उदाहरण: यदि E पॉइंटर प्रकार की अभिव्यक्ति है, तो * E एक लैवल्यू एक्सप्रेशन है, जो उस ऑब्जेक्ट या फ़ंक्शन को संदर्भित करता है, जिसमें E इंगित करता है। एक अन्य उदाहरण के रूप में, एक फ़ंक्शन को कॉल करने का परिणाम जिसका वापसी प्रकार एक लैवल्यू संदर्भ है एक लैवल्यू है। उदाहरण का]
  • एक xvalue ("ईएक्सपायरिंग" मूल्य) भी एक वस्तु को संदर्भित करता है, आमतौर पर अपने जीवनकाल के अंत में (ताकि इसके संसाधनों को ले जाया जा सके, उदाहरण के लिए)। एक xvalue कुछ विशेष प्रकार के भावों का परिणाम है, जिसमें rvalue सन्दर्भ (8.3.2) शामिल हैं। [उदाहरण: एक फ़ंक्शन को कॉल करने का परिणाम जिसका वापसी प्रकार एक रैवल्यू संदर्भ है, एक xvalue है। उदाहरण का]
  • एक ग्लव्यू ("सामान्यीकृत" लैवल्यू) एक लैवल्यू या एक एक्सवल्यू है।
  • एक rvalue (तथाकथित, ऐतिहासिक रूप से, क्योंकि rvalues ​​एक असाइनमेंट एक्सप्रेशन के दाईं ओर दिखाई दे सकता है) एक xvalue, एक
    अस्थायी ऑब्जेक्ट (12.2) या इसके अधीन सबऑब्जेक्ट , या मान जो
    किसी ऑब्जेक्ट से संबद्ध नहीं है ।
  • एक प्रचलन ("शुद्ध" अवतरण) एक प्रचलन है जो एक xvalue नहीं है। [उदाहरण: एक फ़ंक्शन को कॉल करने का परिणाम जिसका वापसी प्रकार एक
    संदर्भ नहीं है एक प्रचलन है। शाब्दिक का मान जैसे कि 12, 7.3e5, या
    सत्य भी एक प्रचलन है। उदाहरण का]

हर अभिव्यक्ति इस वर्गीकरण में मौलिक वर्गीकरणों में से एक है: लवल्यू, ज़वल्यू, या प्रील्यूव। किसी अभिव्यक्ति की इस संपत्ति को उसकी मूल्य श्रेणी कहा जाता है।

लेकिन मैं इस बारे में बिल्कुल निश्चित नहीं हूं कि यह उपधारा अवधारणाओं को स्पष्ट रूप से समझने के लिए पर्याप्त है, क्योंकि "आमतौर पर" वास्तव में सामान्य नहीं है, "अपने जीवनकाल के अंत के पास" वास्तव में ठोस नहीं है, "व्याप्त संदर्भों को शामिल करना" वास्तव में स्पष्ट नहीं है, और "उदाहरण: एक फ़ंक्शन को कॉल करने का परिणाम जिसका वापसी प्रकार एक रव्यू संदर्भ है, एक xvalue है।" लगता है जैसे सांप अपनी पूंछ काट रहा हो।

प्राथमिक मूल्य श्रेणियों

प्रत्येक अभिव्यक्ति ठीक एक प्राथमिक मूल्य श्रेणी से संबंधित है। ये मान श्रेणियां lvalue, xvalue और prvalue श्रेणियां हैं।

lvalues

E की अभिव्यक्ति Lvalue श्रेणी से है, यदि केवल और यदि E एक ऐसी इकाई को संदर्भित करता है, जिसमें ALREADY की पहचान (पता, नाम या उपनाम) है, जो इसे E के बाहर सुलभ बनाता है।

#include <iostream>

int i=7;

const int& f(){
    return i;
}

int main()
{
    std::cout<<&"www"<<std::endl; // The expression "www" in this row is an lvalue expression, because string literals are arrays and every array has an address.  

    i; // The expression i in this row is an lvalue expression, because it refers to the same entity ...
    i; // ... as the entity the expression i in this row refers to.

    int* p_i=new int(7);
    *p_i; // The expression *p_i in this row is an lvalue expression, because it refers to the same entity ...
    *p_i; // ... as the entity the expression *p_i in this row refers to.

    const int& r_I=7;
    r_I; // The expression r_I in this row is an lvalue expression, because it refers to the same entity ...
    r_I; // ... as the entity the expression r_I in this row refers to.

    f(); // The expression f() in this row is an lvalue expression, because it refers to the same entity ...
    i; // ... as the entity the expression f() in this row refers to.

    return 0;
}

XValues

अभिव्यक्ति ई xvalue श्रेणी का है यदि और केवल यदि यह है

- किसी फ़ंक्शन को कॉल करने का परिणाम, चाहे वह स्पष्ट रूप से हो या स्पष्ट रूप से, जिसका वापसी प्रकार किसी वस्तु के लौटाए गए प्रकार का संदर्भ है, या

int&& f(){
    return 3;
}

int main()
{
    f(); // The expression f() belongs to the xvalue category, because f() return type is an rvalue reference to object type.

    return 0;
}

- वस्तु प्रकार, या के लिए एक संदर्भ के लिए एक डाली

int main()
{
    static_cast<int&&>(7); // The expression static_cast<int&&>(7) belongs to the xvalue category, because it is a cast to an rvalue reference to object type.
    std::move(7); // std::move(7) is equivalent to static_cast<int&&>(7).

    return 0;
}

- एक क्लास मेंबर एक्सेस एक्सप्रेशन जिसमें नॉन-रेफरेंस डेटा नॉन-रेफरेंस टाइप का एक मेंबर आब्जेक्ट होता है जिसमें ऑब्जेक्ट एक्सप्रेशन, या

struct As
{
    int i;
};

As&& f(){
    return As();
}

int main()
{
    f().i; // The expression f().i belongs to the xvalue category, because As::i is a non-static data member of non-reference type, and the subexpression f() belongs to the xvlaue category.

    return 0;
}

- एक पॉइंटर-टू-मेंबर एक्सप्रेशन जिसमें पहला ऑपरेंड एक ज़वल्यू है और दूसरा ऑपरेंड डेटा मेंबर का पॉइंटर है।

ध्यान दें कि ऊपर दिए गए नियमों का प्रभाव यह है कि वस्तुओं के नाम के संदर्भों को अंतराल के रूप में माना जाता है और वस्तुओं के लिए अनाम संदर्भों को xvalues ​​के रूप में माना जाता है; कार्यों के संदर्भों के संदर्भों को नाम के रूप में माना जाता है या नहीं।

#include <functional>

struct As
{
    int i;
};

As&& f(){
    return As();
}

int main()
{
    f(); // The expression f() belongs to the xvalue category, because it refers to an unnamed rvalue reference to object.
    As&& rr_a=As();
    rr_a; // The expression rr_a belongs to the lvalue category, because it refers to a named rvalue reference to object.
    std::ref(f); // The expression std::ref(f) belongs to the lvalue category, because it refers to an rvalue reference to function.

    return 0;
}

prvalues

अभिव्यक्ति E का संबंध प्रवल्यू श्रेणी से है यदि और केवल यदि ई न तो लैवल्यू से संबंधित है और न ही एक्सवल्यू श्रेणी से।

struct As
{
    void f(){
        this; // The expression this is a prvalue expression. Note, that the expression this is not a variable.
    }
};

As f(){
    return As();
}

int main()
{
    f(); // The expression f() belongs to the prvalue category, because it belongs neither to the lvalue nor to the xvalue category.

    return 0;
}

मिश्रित मूल्य श्रेणियों

दो और महत्वपूर्ण मिश्रित मूल्य श्रेणियां हैं। ये मूल्य श्रेणियां रूवेल्यू और ग्लव्यू श्रेणियां हैं।

rvalues

अभिव्यक्ति E का संबंध प्रतिद्वंद्वियों की श्रेणी से है, यदि और केवल यदि ई xvalue श्रेणी से संबंधित है, या प्रचलन वर्ग से संबंधित है।

ध्यान दें कि इस परिभाषा का अर्थ है कि अभिव्यक्ति ई का संबंध प्रतिद्वंद्वियों की श्रेणी से है, यदि और केवल तभी ई का तात्पर्य उस इकाई से है जिसकी कोई पहचान नहीं है, जो इसे ई वाईईटी के बाहर सुलभ बनाती है।

glvalues

अभिव्यक्ति E का संबंध ग्वालियर श्रेणी से है, यदि और केवल यदि ई का संबंध लैवल्यू श्रेणी से है, या xvalue श्रेणी से है।

एक व्यावहारिक नियम

स्कॉट मेयर ने अंतराल से अंतराल को अलग करने के लिए अंगूठे का एक बहुत ही उपयोगी नियम प्रकाशित किया है।

  • यदि आप एक अभिव्यक्ति का पता ले सकते हैं, तो अभिव्यक्ति एक अंतराल है।
  • यदि एक अभिव्यक्ति का प्रकार एक लवल्यू संदर्भ (जैसे, टीएंड या कास्ट टी एंड आदि) है, तो वह अभिव्यक्ति एक लवल्यू है।
  • अन्यथा, अभिव्यक्ति एक प्रतिद्वंद्विता है। वैचारिक रूप से (और आमतौर पर वास्तव में भी), प्रतिद्वंद्विता अस्थायी वस्तुओं के अनुरूप होती है, जैसे कि फ़ंक्शंस से लौटे या निहितार्थ रूपांतरण के माध्यम से बनाई गई। अधिकांश शाब्दिक मूल्य (जैसे, 10 और 5.3) भी व्याप्त हैं।

3
अंतराल के लिए सभी उदाहरण और xvalues ​​के लिए सभी उदाहरण glvalues ​​के लिए भी उदाहरण हैं। संपादन के लिए धन्यवाद!
डेनियल सांडोर

1
तुम सही हो। तीन प्राथमिक मूल्य श्रेणियां पर्याप्त हैं। रेवले नेकसेरी नहीं है। मुझे लगता है कि सुविधा के लिए मानक और चमक में मानक है।
डैनियल सैंडर

1
चर को समझने struct As{void f(){this;}}का कठिन समय था this। मैंने सोचा कि thisएक अंतराल होना चाहिए। जब तक मानक 9.3.2 कहता है: गैर-स्थैतिक (9.3) सदस्य फ़ंक्शन के शरीर में, कीवर्ड यह एक प्रचलित अभिव्यक्ति है।
23

3
@ r0ng thisएक प्रचलन है, लेकिन एक लैवल्यू *thisहै
Xeverous

1
"www" हमेशा एक ही पता नहीं होता है। यह एक अंतराल है क्योंकि यह एक सरणी है
वैली

35

C ++ 03 की श्रेणियां अभिव्यक्ति विशेषताओं में सही ढंग से प्रतिद्वंद्वियों के संदर्भों को दर्ज करने के लिए प्रतिबंधित हैं।

उनके परिचय के साथ, यह कहा गया था कि एक अनाम रवैल्यू संदर्भ एक रिवेल्यू का मूल्यांकन करता है, जैसे कि अधिभार रिज़ॉल्यूशन रेवल्यू रिफ़ंड बाइंडिंग को पसंद करेगा, जो इसे कॉपी कंस्ट्रक्टर्स के ऊपर मूव कंस्ट्रक्टर्स का चयन करेगा। लेकिन यह पाया गया कि यह चारों ओर समस्याओं का कारण बनता है, उदाहरण के लिए डायनामिक प्रकार और योग्यता के साथ।

यह दिखाने के लिए, विचार करें

int const&& f();

int main() {
  int &&i = f(); // disgusting!
}

प्री-xvalue ड्राफ्ट पर, यह अनुमति दी गई थी, क्योंकि C ++ 03 में, गैर-वर्ग प्रकारों के rvalues ​​कभी भी cv- योग्य नहीं होते हैं। लेकिन यह इरादा है कि यह constरवैल्यू-रेफरेंस के मामले में लागू होता है, क्योंकि यहां हम ऑब्जेक्ट्स (= मेमोरी!) का उल्लेख करते हैं, और नॉन-क्लास रिवल्यूशंस से कॉन्स्ट को ड्राप करना मुख्य रूप से इस कारण से है कि आसपास कोई ऑब्जेक्ट नहीं है।

गतिशील प्रकारों के लिए मुद्दा समान प्रकृति का है। C ++ 03 में, वर्ग प्रकार के rvalues ​​में एक ज्ञात गतिशील प्रकार है - यह उस अभिव्यक्ति का स्थिर प्रकार है। क्योंकि यह एक और तरीका है, तो आपको संदर्भ या डीरेफेरेंस की आवश्यकता होती है, जो एक अंतराल का मूल्यांकन करते हैं। अनाम अनाम संदर्भों के साथ यह सही नहीं है, फिर भी वे बहुरूपतापूर्ण व्यवहार दिखा सकते हैं। तो इसे हल करने के लिए,

  • अनाम रूवल संदर्भ xvalues बन जाते हैं । वे योग्य हो सकते हैं और संभावित रूप से उनके गतिशील प्रकार अलग हैं। वे इरादा के अनुसार ओवरलोडिंग के दौरान रेवल्यू रेफरेंस पसंद करते हैं, और नॉन-कॉन्स्टल लैवल्यू रेफरेंस के लिए बाध्य नहीं होंगे।

  • पहले जो एक रवैल्यू था (शाब्दिक, गैर-संदर्भ प्रकारों के लिए कलाकारों द्वारा बनाई गई वस्तुएं) अब एक प्रचलन बन गया है । ओवरलोडिंग के दौरान उनकी समान प्राथमिकता होती है।

  • पहले क्या था एक लैवल्यू एक लैवल्यू रहता है।

और दो समूहों को उन पर कब्जा करने के लिए किया जाता है जो योग्य हो सकते हैं और अलग-अलग गतिशील प्रकार ( glvalues ) हो सकते हैं और वे जहां ओवरलोडिंग पसंद करते हैं rvalue रेफरेंस बाइंडिंग ( rvalues )।


1
उत्तर स्पष्ट है। xvalue सिर्फ rvalue है जो cv- योग्य और गतिशील टाइप किया जा सकता है!
ligand

26

मैं लंबे समय तक इससे जूझता रहा, जब तक कि मैं मूल्य श्रेणियों के cppreference.com स्पष्टीकरण पर नहीं आ गया ।

यह वास्तव में सरल है, लेकिन मुझे लगता है कि इसे अक्सर इस तरह से समझाया जाता है कि इसे याद रखना मुश्किल है। यहाँ इसे बहुत ही योजनाबद्ध तरीके से समझाया गया है। मैं पृष्ठ के कुछ हिस्सों को उद्धृत करूँगा:

प्राथमिक श्रेणियां

प्राथमिक मूल्य श्रेणियां अभिव्यक्ति के दो गुणों के अनुरूप हैं:

  • पहचान है : यह निर्धारित करना संभव है कि क्या अभिव्यक्ति उसी इकाई को किसी अन्य अभिव्यक्ति के रूप में संदर्भित करती है, जैसे कि वस्तुओं के पते की तुलना करके या उनके द्वारा पहचाने गए कार्यों (प्रत्यक्ष या अप्रत्यक्ष रूप से);

  • से ले जाया जा सकता है : मूव कंस्ट्रक्टर, मूव असाइनमेंट ऑपरेटर, या एक और फंक्शन ओवरलोड, जो इम्प्लीमेंट्स मूवमेंट को स्थानांतरित करता है, अभिव्यक्ति को बाँध सकता है।

अभिव्यक्तियाँ:

  • पहचान और से कहा जाता है हटाया नहीं जा सकता भाव lvalue ;
  • पहचान है और से ले जाया जा सकता है xvalue अभिव्यक्ति कहा जाता है ;
  • पहचान नहीं है और से चले जा सकते हैं कहा जाता है भाव अभिव्यक्ति ;
  • पहचान नहीं है और से स्थानांतरित नहीं किया जा सकता उपयोग नहीं कर रहे हैं।

lvalue

एक अंतराल ("बाएं मान") अभिव्यक्ति एक अभिव्यक्ति है जिसकी पहचान है और इससे स्थानांतरित नहीं किया जा सकता है

rvalue (C ++ 11 तक), prvalue (C ++ 11 के बाद से)

एक प्रचलन ("शुद्ध अवतरण") अभिव्यक्ति एक अभिव्यक्ति है जिसकी पहचान नहीं है और इससे स्थानांतरित किया जा सकता है

XValue

एक xvalue ("समाप्ति मूल्य") अभिव्यक्ति एक अभिव्यक्ति है जिसकी पहचान है और इससे स्थानांतरित किया जा सकता है

glvalue

एक ग्लव्यू ("सामान्यीकृत लैवल्यू") अभिव्यक्ति एक अभिव्यक्ति है जो या तो एक लैवल्यू या एक एक्सवल्यू है। इसकी पहचान है । इसे स्थानांतरित नहीं किया जा सकता है या नहीं।

rvalue (C ++ 11 के बाद से)

एक rvalue ("सही मान") अभिव्यक्ति एक अभिव्यक्ति है जो या तो एक प्रचलन या एक xvalue है। इससे स्थानांतरित किया जा सकता है । इसकी पहचान हो भी सकती है और नहीं भी।


1
कुछ पुस्तकों में, xvalues ​​को दिखाया गया है कि उनका एक्स "विशेषज्ञ" या "असाधारण" से आया है
noɥʇʎԀʎzɐɹƆ

और अधिक महत्वपूर्ण बात, उनकी सभी व्यापक उदाहरण सूची।
सिरो सेंटिल्ली 冠状 病毒 iro 事件 法轮功 '

19

ये नई श्रेणियां मौजूदा प्रतिद्वंद्विता और लवल्यू श्रेणियों से कैसे संबंधित हैं?

एक C ++ 03 लैवल्यू अभी भी C ++ 11 लैवल्यू है, जबकि C ++ 03 रिवेल्यू को C ++ 11 में एक प्रवल्यू कहा जाता है।


14

ऊपर दिए गए उत्कृष्ट उत्तरों में से एक परिशिष्ट, एक ऐसे बिंदु पर जिसने मुझे स्ट्रॉन्स्ट्रुप पढ़ने के बाद भी भ्रमित किया और मुझे लगा कि मैंने रवैल / लैवल्यू डिस्टिंक्शन को समझा है। जब आप देखते है

int&& a = 3,

यह int&&एक प्रकार के रूप में पढ़ने और निष्कर्ष निकालने के लिए बहुत लुभावना है a। यह:

int&& a = 3;
int&& c = a; //error: cannot bind 'int' lvalue to 'int&&'
int& b = a; //compiles

aका नाम है और वास्तव में एक लैवल्यू है। &&के प्रकार के रूप में मत सोचो a; यह सिर्फ आपको बता रहा है कि आपको क्या करने aकी अनुमति है।

यह विशेष रूप T&&से कंस्ट्रक्टरों में टाइप तर्क के लिए मायने रखता है । अगर आप लिखेंगे

Foo::Foo(T&& _t) : t{_t} {}

आप की प्रतिलिपि बनाएगा _tमें t। आप की जरूरत है

Foo::Foo(T&& _t) : t{std::move(_t)} {}अगर आप चलना चाहते हैं। क्या मेरे संकलक ने मुझे चेतावनी दी थी जब मैं बाहर निकल जाऊंगा move!


1
मुझे लगता है कि इस जवाब को स्पष्ट किया जा सकता है। "क्या aबांधने की अनुमति है": निश्चित रूप से, लेकिन पंक्ति 2 और 3 में आपके चर सी और बी हैं, और यह एक ऐसा नहीं है जो बांधता है, और किस प्रकार का aयहाँ अप्रासंगिक है, है ना? aघोषित होने पर लाइनें समान होंगी int a। यहाँ वास्तविक मुख्य अंतर यह है कि लाइन 1 में 3 constको बाँधने की आवश्यकता नहीं है
फेलिक्स डॉम्बेक

12

जैसा कि पिछले जवाबों ने थ्योरी को वैल्यू कैटिगरी के पीछे कवर किया था, एक और चीज है जिसे मैं जोड़ना चाहता हूं: आप वास्तव में इसके साथ खेल सकते हैं और इसे टेस्ट कर सकते हैं।

मूल्य श्रेणियों के साथ कुछ हाथों के प्रयोग के लिए, आप डिक्लेपट स्पेसियर का उपयोग कर सकते हैं । इसका व्यवहार स्पष्ट रूप से तीन प्राथमिक मूल्य श्रेणियों (xvalue, lvalue, और prvalue) के बीच अंतर करता है।

प्रीप्रोसेसर का उपयोग करने से हमें कुछ टाइपिंग की बचत होती है ...

प्राथमिक श्रेणियां:

#define IS_XVALUE(X) std::is_rvalue_reference<decltype((X))>::value
#define IS_LVALUE(X) std::is_lvalue_reference<decltype((X))>::value
#define IS_PRVALUE(X) !std::is_reference<decltype((X))>::value

मिश्रित श्रेणियां:

#define IS_GLVALUE(X) (IS_LVALUE(X) || IS_XVALUE(X))
#define IS_RVALUE(X) (IS_PRVALUE(X) || IS_XVALUE(X))

अब हम मूल्य श्रेणी पर cppreference से सभी (लगभग) सभी उदाहरणों को पुन: उत्पन्न कर सकते हैं ।

यहाँ C ++ 17 के साथ कुछ उदाहरण दिए गए हैं (terse static_assert के लिए):

void doesNothing(){}
struct S
{
    int x{0};
};
int x = 1;
int y = 2;
S s;

static_assert(IS_LVALUE(x));
static_assert(IS_LVALUE(x+=y));
static_assert(IS_LVALUE("Hello world!"));
static_assert(IS_LVALUE(++x));

static_assert(IS_PRVALUE(1));
static_assert(IS_PRVALUE(x++));
static_assert(IS_PRVALUE(static_cast<double>(x)));
static_assert(IS_PRVALUE(std::string{}));
static_assert(IS_PRVALUE(throw std::exception()));
static_assert(IS_PRVALUE(doesNothing()));

static_assert(IS_XVALUE(std::move(s)));
// The next one doesn't work in gcc 8.2 but in gcc 9.1. Clang 7.0.0 and msvc 19.16 are doing fine.
static_assert(IS_XVALUE(S().x)); 

एक बार जब आप प्राथमिक श्रेणी का पता लगाते हैं तो मिश्रित श्रेणियां उबाऊ होती हैं।

कुछ और उदाहरणों (और प्रयोग) के लिए, कंपाइलर एक्सप्लोरर पर निम्न लिंक देखें । हालांकि, विधानसभा को पढ़ने से परेशान न हों। मैंने यह सुनिश्चित करने के लिए बहुत सारे संकलक जोड़े कि यह सभी आम संकलक के पार काम करता है।


मुझे लगता है कि #define IS_GLVALUE(X) IS_LVALUE(X) || IS_XVALUE(X)वास्तव में #define IS_GLVALUE(X) (IS_LVALUE(X) || IS_XVALUE(X))अन्यथा देखना चाहिए कि क्या होता है अगर आप &&दो IS_GLVALUE
गैब्रियल डेविलर्स 23:14
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.