वापसी का प्रकार: '?'


208

पहला संदर्भ क्यों लौटता है?

int x = 1;
int y = 2;
(x > y ? x : y) = 100;

जबकि दूसरा नहीं करता है?

int x = 1;
long y = 2;
(x > y ? x : y) = 100;

दरअसल, दूसरे ने बिल्कुल भी संकलन नहीं किया - "असाइनमेंट के बचे हुए अंतराल को नहीं"।


1
हम्म, रोटी पकाने के लिए एक विशेष मामला खोजने की तरह, यह एक बार नहीं आया
उल्टा


अभिव्यक्ति को एक प्रकार का असाइन करने के रूप में कम से कम एक शब्द का एक कास्ट होगा, इस शब्द का कोई एल-मूल्य नहीं होगा।
यवेस डाएव

जवाबों:


173

भाव वापसी प्रकार नहीं हैं, उनके पास एक प्रकार है और - जैसा कि नवीनतम C ++ मानक में जाना जाता है - एक मूल्य श्रेणी।

एक सशर्त अभिव्यक्ति एक स्वर या एक लय हो सकती है । यह इसकी मूल्य श्रेणी है। (यह कुछ हद तक एक सरलीकरण है, C++11हमारे पास lvalues, xvalues ​​और prvalues ​​हैं।)

बहुत व्यापक और सरल शब्दों में, एक अंतराल स्मृति में एक वस्तु को संदर्भित करता है और एक अंतराल केवल एक मूल्य है जो जरूरी नहीं कि स्मृति में किसी वस्तु से जुड़ा हो।

असाइनमेंट एक्सप्रेशन किसी ऑब्जेक्ट को वैल्यू प्रदान करता है, इसलिए जो चीज़ असाइन की जा रही है, वह एक लैवल्यू होनी चाहिए ।

एक सशर्त अभिव्यक्ति ( ?:) के लिए एक लैवल्यू (फिर से, व्यापक और सरल शब्दों में) होने के लिए, दूसरे और तीसरे ऑपरेंड को एक ही प्रकार के अंतराल होना चाहिए । ऐसा इसलिए है क्योंकि सशर्त अभिव्यक्ति का प्रकार और मूल्य श्रेणी संकलन के समय पर निर्धारित किया जाता है और यह उचित होना चाहिए कि क्या स्थिति सच है या नहीं। ऑपरेंड में से एक एक अलग प्रकार का अन्य मैच के लिए परिवर्तित किया जाना चाहिए तो सशर्त अभिव्यक्ति एक नहीं हो सकता lvalue इस रूपांतरण के परिणाम एक नहीं होगा के रूप में lvalue

आईएसओ / आईईसी 14882: 2011 संदर्भ:

3.10 [basic.lval] अंतराल और अंतराल (मूल्य श्रेणियों के बारे में)

5.15 [expr.cond] सशर्त ऑपरेटर (सशर्त अभिव्यक्ति किस प्रकार और मूल्य श्रेणी के लिए नियम हैं):

5.17 [expr.ass] असाइनमेंट और कंपाउंड असाइनमेंट ऑपरेटर्स (आवश्यकता है कि असाइनमेंट के lhs एक परिवर्तनीय अंतराल होना चाहिए)


3
और जब xvalue और prvalue पर पढ़ रहा था (क्योंकि मैंने आपके उत्तर से पहले उनके बारे में नहीं सुना था) तो मुझे यह बहुत आसान पोस्ट आया: stackoverflow.com/questions/3601602/…
19-11 को शराबी

an rvalue is just a value that may not necessarily be *attached* to an object in memory.क्या आप इसे और सरल शब्द में समझा सकते हैं? । इसके अलावा आपका क्या मतलब है type and value *category*? धन्यवाद
श्रीअनुबिस

@ सस्ती: prvalue, xvalue, glvalueमूल्य श्रेणियां हैं।
Xeo

@ Xeo मैं मदद की सराहना करता हूं, लेकिन क्या आप बता सकते हैं कि एक प्रतिद्वंद्विता से उसका क्या मतलब है बस एक मूल्य है जो जरूरी नहीं कि स्मृति में किसी वस्तु से जुड़ा हो। ? उदाहरण के साथ?
Mr.Anubis

@SoulReaper: मुझे लगता है कि वह चीजों के बारे में बात कर रहा है की तरह है true, this, enumमान। वे चीजें प्रचलित हैं ("शुद्ध" नियम), लेकिन स्मृति में नहीं रहते हैं।
Xeo

57

तिर्यक ?:अभिव्यक्ति का प्रकार इसके दूसरे और तीसरे तर्क का सामान्य प्रकार है। यदि दोनों प्रकार समान हैं, तो आपको एक संदर्भ वापस मिलता है। यदि वे एक दूसरे के लिए परिवर्तनीय हैं, तो एक चुना जाता है और दूसरा परिवर्तित हो जाता है (इस मामले में पदोन्नत)। चूँकि आप एक अस्थायी (परिवर्तित / संवर्धित चर) के लिए एक अंतराल संदर्भ नहीं लौटा सकते हैं, इसका प्रकार एक मूल्य प्रकार है।


लेकिन x से अधिक y है, इसलिए इस विशेष मामले के लिए प्रचार की कोई आवश्यकता नहीं है, यह y के संदर्भ को वापस कर सकता है। हम्म ... लेकिन मैं सहमत हूं, यह अजीब होगा।
योला

1
@ Mr.TAMER: मैं मानक के माध्यम से खुदाई करना चाहता हूं। : <
Xio

3
@ वायोला: चूंकि C ++ में प्रकार एक संकलित समय अवधारणा हैं, इसलिए अभिव्यक्ति का वास्तविक वापसी मूल्य कोई मायने नहीं रखता है।
Xeo

1
आपको एक संदर्भ वापस नहीं मिलता है, आपको अंतराल मिलता है।
सुमा

1
@ Xeo: C ++ शब्दावली में नहीं, हालांकि;)
सेबस्टियन मच

19

यह एक अंतराल को वापस नहीं कर सकता क्योंकि इसके प्रकार के xमिलान के प्रकार को स्पष्ट रूप से बढ़ावा देना होगा y(क्योंकि दोनों पक्ष :एक ही प्रकार के नहीं हैं), और इसके साथ ही इसे एक अस्थायी बनाना होगा।


मानक क्या कहता है? ( n1905 )

अभिव्यक्तियाँ 5.17 असाइनमेंट और कंपाउंड असाइनमेंट ऑपरेटर

5.17 / 3

यदि दूसरे और तीसरे ऑपरेंड के अलग-अलग प्रकार हैं, और या तो (संभवतः सीवी-योग्य) वर्ग प्रकार है, तो उन प्रत्येक ऑपरेंड को दूसरे के प्रकार में बदलने का प्रयास किया जाता है। यह निर्धारित करने की प्रक्रिया कि क्या T1 के एक ऑपरेंड एक्सप्रेशन E1 को एक ऑपरेंड एक्सप्रेशन से मिलान करने के लिए परिवर्तित किया जा सकता है, टाइप 2 के E2 को निम्न प्रकार से परिभाषित किया गया है:

- यदि E2 एक लवल्यू है: E1 को E2 से मिलान किया जा सकता है यदि E1 को "टी 2 के संदर्भ में" प्रकार (खंड 4) में रूपांतरित किया जा सकता है, तो बाधा के अधीन है कि रूपांतरण में संदर्भ को सीधे बाँधना होगा (8.5.3) ) ई 1 को।

- यदि E2 एक प्रतिद्वंद्विता है, या यदि ऊपर रूपांतरण नहीं किया जा सकता है:

- यदि E1 और E2 का वर्ग प्रकार है, और अंतर्निहित वर्ग प्रकार समान हैं या एक दूसरे का आधार वर्ग है: E1 को E2 से मिलान करने के लिए परिवर्तित किया जा सकता है यदि T2 का वर्ग उसी प्रकार का है, या निम्न का आधार वर्ग है T1 की कक्षा, और T2 की cv- योग्यता के समान ही cv- योग्यता है, या T1 की cv- योग्यता से अधिक cv- योग्यता है। यदि रूपांतरण लागू किया जाता है, तो E1 को T2 के एक प्रकार में बदल दिया जाता है जो अभी भी मूल स्रोत वर्ग ऑब्जेक्ट (या उसके बाद उपयुक्त उप-विषय) को संदर्भित करता है। [ नोट: वह है, कोई प्रतिलिपि नहीं बनाई गई है। - एंड नोट ] E1 से T2 के एक अस्थायी प्रकार की प्रतिलिपि बनाकर और परिवर्तित ऑपरेंड के रूप में उस अस्थायी का उपयोग करके।

अन्यथा (यानी, यदि E1या ई 2 में एक गैर-वर्ग प्रकार है, या यदि उनके पास दोनों प्रकार के वर्ग हैं, लेकिन अंतर्निहित कक्षाएं या तो समान या एक दूसरे के आधार वर्ग नहीं हैं): E1 को E2 से मिलान करने के लिए परिवर्तित किया जा सकता है यदि E1 हो सकता है स्पष्ट रूप से उस प्रकार में परिवर्तित हो जाता है, जिसमें E2 होता है, यदि E2 एक अवक्षेप में परिवर्तित हो जाता है (या इसका प्रकार है, यदि E2 एक प्रचलन है)।

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


5.17 / 4

यदि दूसरा और तीसरा ऑपरेंड लैवल्यूज़ हैं और एक ही प्रकार के हैं, तो परिणाम उस प्रकार का है और एक लैवल्यू है और यह बिट-फ़ील्ड है यदि दूसरा या तीसरा ऑपरेंड थोड़ा-फ़ील्ड है, या यदि दोनों बिट हैं- खेत।


5.17 / 5

अन्यथा, परिणाम एक प्रतिद्वंद्विता है। यदि दूसरे और तीसरे ऑपरेंड में एक ही प्रकार नहीं है, और या तो (संभवतः cv-योग्य) वर्ग प्रकार है, तो ओवरलोड रिज़ॉल्यूशन का उपयोग ऑपरेशंस (13.3.1.2, 13.6) पर लागू होने वाले रूपांतरणों को निर्धारित करने के लिए किया जाता है (13.3.1.2, 13.6) । यदि अधिभार संकल्प विफल हो जाता है, तो कार्यक्रम बीमार है। अन्यथा, इस प्रकार निर्धारित किए गए रूपांतरणों को लागू किया जाता है, और इस खंड के शेष के लिए मूल ऑपरेंड के स्थान पर परिवर्तित ऑपरेंड का उपयोग किया जाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.