2011-06-16 7 views
7

को देखते हुए:क्या मानक खंड इस लालू-से-रावल्यू रूपांतरण को अनिवार्य करता है?

int main() { 
    int x = 0; 
    int y = x; // <--- 
} 

किसी कृपया मुझे जो मानक (2003 पसंदीदा) के खंड बता सकते हैं वस्तु y की initialisation में rvalue करने के लिए से अभिव्यक्ति x lvalue के रूपांतरण जनादेश?

(या, अगर मैं गलत हूँ और ऐसी कोई रूपांतरण होता है, तो मैं वह भी जानकारी चाहते हैं!)

+0

मुझे नहीं लगता कि ऐसा कोई रूपांतरण होता है। किसी भी मामले में वे आदिम प्रकार हैं, लेकिन यहां तक ​​कि यदि आपके पास गैर-तुच्छ कन्स्ट्रक्टर थे, तो आपने जो लिखा था वह प्रतिलिपि करेगा, कभी भी चालक कन्स्ट्रक्टर नहीं। –

+0

http://chat.stackoverflow.com/transcript/message/847067#847067 पर चर्चा प्रासंगिक हो सकती है। –

+0

@ केरेक: लेकिन मूल्य का उपयोग करने की आवश्यकता है। ऐसा रूपांतरण कैसे हो सकता है _not_? (और 2003 में कोई चालक कन्स्ट्रक्टर नहीं हैं)। –

उत्तर

7

मुझे ऑब्जेक्ट में संग्रहीत मूल्य के रूप में वास्तविक वस्तुओं और रावल्यू के रूप में lvalue-s के बारे में सोचने के लिए यह आसान लगता है (यदि शायद 100% सटीक नहीं है)। अभिव्यक्ति x एक lvalue अभिव्यक्ति है कि वस्तु x पहली पंक्ति में परिभाषित के लिए संदर्भित करता है, लेकिन जब एक विशेष प्रकार के एक काम के दाहिने हाथ की ओर है कि एक उपयोगकर्ता परिभाषित प्रकार वास्तविक मूल्य पढ़ने के लिए है नहीं है, और ऐसे ही उपयोग वह जगह है जहां लैवल्यू से रैवल्यू का रूपांतरण किया जाता है: ऑब्जेक्ट की सामग्री को पढ़ना।

मानक में विशिष्ट खंड के रूप में जो रूपांतरण को निर्देशित करता है ... अच्छा, निकटतम जो मैं सोच सकता हूं वह 4.1 है [रूपांतरण।lvalue]/2 (Rvalue रूपांतरण के लिए Lvalue):

लालू द्वारा इंगित वस्तु में निहित मूल्य रावल परिणाम है।

आवश्यकता है कि काम के दाहिने हाथ की ओर एक rvalue या तो अस्पष्ट या 5.17 [expr.ass] से लापता है, लेकिन उस मामले या निम्न अभिव्यक्ति एक त्रुटि होगी के बाद से आरएचएस है एक rvalue और वहाँ कोई rvalue करने वाली lvalue रूपांतरण है:

int x = 5; 

संपादित करें: प्रारंभ के लिए, 8.5 [dcl.init]/14, पिछले राज्यों (जोर मेरा) (जो मूल प्रकारों को संदर्भित करता है) गोली:

  • अन्यथा, प्रारंभिक ऑब्जेक्ट का आरंभिक मान प्रारंभिक अभिव्यक्ति अभिव्यक्ति के (0 संभवतः रूपांतरित) मान है। [...] वहाँ का मतलब है

कि मूल्य अपने उदाहरण में lvalue अभिव्यक्ति पढ़ है कि (अर्थात एक rvalue करने के लिए परिवर्तित)। किसी भी दर पर असाइनमेंट को संदर्भित करने वाले पिछले पैराग्राफ को यहां लागू किया जा सकता है: यदि प्रारंभिकरण को रैवल्यू की बजाय, int i = 0; अभिव्यक्ति की आवश्यकता होगी।

+0

अच्छा एक। मुझे लगता है कि यह एक सुंदर ठोस कटौती है। :) –

+0

"असाइनमेंट का दायां हाथ एक आवश्यकता है जो या तो 5.17 [expr.ass] से अंतर्निहित या अनुपलब्ध है, लेकिन यह मामला है या अन्यथा निम्न अभिव्यक्ति एक त्रुटि होगी क्योंकि rhs एक रावल्यू है और कोई रावल-टू-लवल्यू रूपांतरण नहीं है "<- यह पूरी तरह से पालन नहीं करता है, तार्किक रूप से। "आरएचएस एक रैवल्यू होना चाहिए, या आरएचएस एक अंतराल होना चाहिए (और बाद वाला सच नहीं हो सकता है इसलिए पहला होना चाहिए)" जो आप कह रहे हैं; मुझे झूठी डिचोटोमी की तरह दिखता है? –

+0

@ टोमालक: नहीं, तर्क यह है कि अभिव्यक्ति का दायां हाथ ** या तो ** एक लालसा या एक रावल होना आवश्यक है, लेकिन दोनों नहीं। अब: * यदि अभिव्यक्ति के दाहिने हाथ की तरफ एक लालू अभिव्यक्ति होना आवश्यक था, तो 'i = 5' असफल हो जाएगा; अभिव्यक्ति मान्य है (असफल नहीं होती है), अभिव्यक्ति के दाएं हाथ की ओर से ergo एक lvalue * की आवश्यकता नहीं हो सकती है।चूंकि एकमात्र अन्य विकल्प एक * रावल्यू * है (कम से कम सी ++ 03 में), तो अभिव्यक्ति 'x = y' lhs के रूप में एक lvalue लेता है (यह मानक में स्पष्ट है) और rhs के रूप में एक rvalue (मैं नहीं कर सका इसके लिए एक सटीक उद्धरण खोजें) –

1

क्या यह आप जो खोज रहे हैं:

§3.10/7

जब भी एक संदर्भ में एक लाभा दिखाई देता है जहां एक रैल्यू की अपेक्षा की जाती है, तो अंतराल को एक रैल्यू में परिवर्तित कर दिया जाता है; 4.1, 4.2, और 4.3 देखें।

और मुझे लगता है कि जब आप int y = x लिखते हैं, यह मूल रूप से प्रतियां मूल्य वस्तु x जो एक lvalue है में निहित है, लेकिन मूल्य अपने आप में एक rvalue इसलिए संदर्भ एक rvalue उम्मीद है।

§4.1/2 कहते हैं,

वस्तु lvalue ने संकेत में निहित मूल्य rvalue परिणाम है।

शायद ये दो उद्धरण आपके संदेह को स्पष्ट करते हैं। अगर मेरी समझ गलत है तो मुझे सही करो। मैं नई चीजें सीखना चाहूंगा।


@ Tomalak की टिप्पणी:

इस के साथ मेरी समस्या यह है कि & y पूर्णांक = एक्स; मान्य है, इसलिए निश्चित रूप से एक्स इस मामले में एक रैल्यू नहीं हो सकता है। मैं नहीं जानता कि कैसे अप्रासंगिक मेरे उदाहरण में फर्क नहीं पड़ता कि, हालांकि

खैर int &y = x मान की प्रतिलिपि नहीं करता है। यह सिर्फ वस्तु का उपनाम बनाता है। लेकिन जैसा कि मैंने पहले कहा था int y = x, मूल रूप से प्रतियांमूल्य जो एक रैवल्यू है। इसलिए, संदर्भ एक रैल्यू की अपेक्षा करता है, क्योंकि एक प्रतिलिपि यहां की जा रही है।

+0

लगभग, लेकिन एक रैल्यू अपेक्षित कहां है? –

+0

इसके साथ मेरी समस्या यह है कि 'int & y = x;' मान्य है, इसलिए इस मामले में 'x' _rvalue_ नहीं हो सकता है। मुझे नहीं पता कि मेरे उदाहरण में अंतर कितना अप्रासंगिक है, हालांकि। –

+0

@ टोमालक गेरेकल: मैंने पहले ही इस उत्तर का उत्तर दिया है, पूर्णांक असाइनमेंट (किसी भी उपयोगकर्ता परिभाषित वर्ग के लिए असाइनमेंट) दाहिने हाथ की तरफ तर्क को एक रावल्यू के रूप में लेता है। अन्यथा, 'int x = 5;' मान्य नहीं होगा, क्योंकि '5' एक रावल्यू है, और एक रावल्यू को एक लाभा में परिवर्तित नहीं किया जा सकता है। –

1

3,10 Lvalues ​​और rvalues ​​

1 हर अभिव्यक्ति या तो एक lvalue या एक rvalue है।

2 एक लाल्व्यू किसी ऑब्जेक्ट या फ़ंक्शन को संदर्भित करता है। कुछ rvalue भाव-उन वर्ग के या cvqualified वर्ग प्रकार- भी objects.47 को देखें)

3 [ध्यान दें: कुछ builtin ऑपरेटरों और समारोह उपज lvalues ​​कहता है। [उदाहरण: यदि ई पॉइंटर प्रकार की अभिव्यक्ति है, तो * ई ऑब्जेक्ट या फ़ंक्शन का संदर्भ देने वाला एक lvalue अभिव्यक्ति है जिसमें E अंक हैं। एक और उदाहरण के रूप में, फ़ंक्शन int & f(); एक लाभा उत्पन्न करता है, इसलिए कॉल एफ() लैवल्यू अभिव्यक्ति है। ]

  1. [नोट: कुछ builin ऑपरेटरों lvalue संचालन की उम्मीद है। [उदाहरण: असाइनमेंट ऑपरेटर सभी बाएं हाथ के संचालन को लालसा होने की उम्मीद करते हैं। ] अन्य बिल्टिन ऑपरेटर रावल, उत्पन्न करते हैं और कुछ उन्हें उम्मीद करते हैं। [उदाहरण: यूनरी और बाइनरी + ऑपरेटर रैवल्यू तर्क और उपज रावल परिणाम की उम्मीद करते हैं। ] धारा 5 में प्रत्येक बिल्टिन ऑपरेटर की चर्चा इंगित करती है कि क्या यह लैवल्यू ऑपरेंड और की अपेक्षा करता है चाहे वह उपज है।]

5 एक समारोह वापस नहीं करता है कि एक संदर्भ एक rvalue है बुला का परिणाम है। उपयोगकर्ता परिभाषित ऑपरेटर फ़ंक्शंस हैं, और क्या ऐसे ऑपरेटर अपेक्षा करते हैं या उपज का लाभ उनके पैरामीटर और रिटर्न प्रकारों द्वारा निर्धारित किया जाता है।

6 कोई व्यंजक जो एक अस्थायी एक nonreference प्रकार के लिए एक डाली से उत्पन्न वस्तु धारण एक rvalue (यह एक वस्तु कार्यात्मक अंकन (5.2.3) का उपयोग करने का स्पष्ट निर्माण भी शामिल है) है।

7 जब भी एक संदर्भ में एक लाभा दिखाई देता है जहां एक रैल्यू अपेक्षित है, लालू को एक रैल्यू में परिवर्तित कर दिया जाता है; 4.1, 4.2, और 4.3 देखें।

8 12,2 में 8.5.3 और की temporaries में संदर्भ प्रारंभ की चर्चा अन्य महत्वपूर्ण संदर्भों में lvalues ​​और rvalues ​​की व्यवहार को दर्शाता है।

9 कक्षा के रावजू में प्रकारों को cvqualified हो सकता है; nonclass rvalues ​​हमेशा cvunqualified प्रकार है। रावल हमेशा पूर्ण प्रकार या शून्य प्रकार होगा; इन प्रकारों के अलावा, lvalues ​​में अपूर्ण प्रकार भी हो सकते हैं।

10 एक वस्तु के लिए एक lvalue आदेश सिवाय इसके कि वर्ग प्रकार का एक rvalue भी कुछ निश्चित परिस्थितियों में अपने दिग्दर्शन संशोधित करने के लिए इस्तेमाल किया जा सकता वस्तु को संशोधित करने में आवश्यक है। [उदाहरण: एक ऑब्जेक्ट (9.3) के लिए बुलाया गया एक सदस्य फ़ंक्शन ऑब्जेक्ट को संशोधित कर सकता है। ]

11 कार्यों को संशोधित नहीं किया जा सकता है, लेकिन फ़ंक्शन पर पॉइंटर्स संशोधित हो सकते हैं।

12 एक अधूरा प्रकार का सूचक संशोधित हो सकता है। प्रोग्राम में किसी बिंदु पर पूर्ण होने पर, ऑब्जेक्ट पर सूचक बिंदु भी संशोधित किया जा सकता है।

13 एक constqualified अभिव्यक्ति की दिग्दर्शन संशोधित करेगा नहीं किया जा (कि अभिव्यक्ति के माध्यम से), कि को छोड़कर अगर यह वर्ग प्रकार का है और एक परिवर्तनशील घटक, कि घटक संशोधित किया जा सकता (7.1.5.1) है ।

14 यदि किसी अभिव्यक्ति का उपयोग पर किया जा सकता है, जिस ऑब्जेक्ट को संदर्भित करता है, अभिव्यक्ति को संशोधित कहा जाता है। एक प्रोग्राम जो एक ऑब्जेक्ट को एक गैर-प्रयोज्य lvalue या रावल्यू अभिव्यक्ति के माध्यम से ऑब्जेक्ट को संशोधित करने का प्रयास करता है, वह खराब है।

15 एक कार्यक्रम निम्नलिखित प्रकार व्यवहार undefined48) है में से एक के अलावा अन्य के lvalue के माध्यम से एक वस्तु का संग्रहीत मूल्य तक पहुँचने के लिए प्रयास करता है: - के गतिशील प्रकार वस्तु, - एक cvqualified के संस्करण वस्तु के गतिशील प्रकार, - एक प्रकार है कि हस्ताक्षर किए या अहस्ताक्षरित वस्तु के गतिशील प्रकार करने के लिए इसी प्रकार है, - एक प्रकार है कि पर हस्ताक्षर किए या अहस्ताक्षरित प्रकार का एक cvqualified संस्करण के लिए इसी ऑब्जेक्ट का गतिशील प्रकार, - कुल या संघ प्रकार है कि अपने सदस्यों के बीच ऊपर उल्लिखित प्रकार के एक (सहित, रिकर्सिवली, एक subaggregate के सदस्य या निहित संघ), शामिल हैं - एक प्रकार है कि एक (संभवतः cvqualified) के आधार वर्ग प्रकार है ऑब्जेक्ट का गतिशील प्रकार, - एक char या हस्ताक्षरित चार प्रकार।

7

मुझे क्या करना मानते हैं कि यह कुछ हद तक सहज है कि (क्या दूसरों को पहले से ही कहा - मूल्य की जरूरत है, ताकि एक स्पष्ट मूल्य उसमें निहित करने के लिए वस्तु डेसिग्नेटर कन्वर्ट करने के लिए की जरूरत है)। सबसे अच्छा मैं 4 एमपी 3:

एक अभिव्यक्ति ई को पूरी तरह से एक प्रकार टी में परिवर्तित किया जा सकता है अगर केवल घोषणा "टी टी = ई;" कुछ आविष्कारित अस्थायी परिवर्तनीय टी (8.5) के लिए अच्छी तरह से गठित है। निहित रूपांतरण का प्रभाव घोषणा और प्रारंभिक प्रदर्शन के रूप में और फिर रूपांतरण के परिणामस्वरूप अस्थायी चर का उपयोग करना जैसा ही है। परिणाम एक लालसा है यदि टी संदर्भ प्रकार (8.3.2) है, और अन्यथा एक रावल्यू है। अभिव्यक्ति ई को एक लाभा के रूप में प्रयोग किया जाता है यदि केवल प्रारंभिकता इसे एक लाभा के रूप में उपयोग करती है।

नोट "यदि और केवल यदि" अंत में - प्रारंभकर्ता की वजह एक rvalue के रूप में, क्योंकि आरंभीकरण एक rvalue (रूपांतरण के परिणाम) के रूप में उपयोग करता है यह प्रयोग किया जाता है। 3.10p7

जब भी एक lvalue एक संदर्भ में, जहां एक rvalue की उम्मीद है, lvalue एक rvalue में बदल जाती है में प्रकट होता है द्वारा तो; 4.1, 4.2, और 4.3 देखें।


संपादित करें: 4p3 प्रवेश करने के लिए पैरा, 8.5p16 में पाया जा सकता आखिरी गोली:

अन्यथा, वस्तु का प्रारंभिक मूल्य प्रारंभ किया जा रहा है (संभवतः परिवर्तित) का मूल्य है प्रारंभकर्ता अभिव्यक्ति।

नीचे दी गई टिप्पणियों को भी नोट करें।

initializer: 
     = initializer-clause 
     (expression-list) 

initializer-clause: 
    assignment-expression 
    { initializer-list ,opt } 
    { } 

अपने उदाहरण में, x एक assignment-expression जो व्याकरण प्रस्तुतियों की इस श्रृंखला का अनुसरण करता है:

conditional-expression ==> 
    logical-or-expression ==> 
     logical-and-expression ==> 
      inclusive-or-expression ==> 
       exclusive-or-expression ==> 
        and-expression ==> 
         equality-expression ==> 
          relational-expression ==> 
           shift-expression ==> 
            additive-expression ==> 
             multiplicative-expression ==> 
              pm-expression ==> 
               cast-expression ==> 
                unary-expression ==> 
                 postfix-expression ==> 
                  primary-expression ==> 
                   id-expression ==> 
                    unqualified-id ==> 
                     identifier 

और एक पहचानकर्ता "है एक lvalue अगर

+0

लेकिन क्या कोई रूपांतरण है? आप 'int' से शुरू करते हैं और आप 'int' के साथ समाप्त होते हैं। अकेले उस तर्क से, मुझे यकीन नहीं है कि पहला उद्धरण लागू होता है। –

+0

@Tomalak एक रूपांतरण वास्तव में एक प्रकार से शुरू नहीं होता है, लेकिन एक * अभिव्यक्ति * के साथ। और अभिव्यक्ति को अंतराल से int के एक रावल्यू में परिवर्तित किया जाता है। –

+0

@litb: यह परिपत्र तर्क है। "एक रूपांतरण है, इस नियम के कारण एक रूपांतरण की आवश्यकता होने पर क्या होता है इसके बारे में बात करते हैं।" –

2

प्रारंभकर्ता follwing व्याकरण है इकाई एक कार्य या चर है "(5.1/4" प्राथमिक अभिव्यक्ति ")।

तो आपके उदाहरण में, = के दाईं ओर अभिव्यक्ति एक अभिव्यक्ति है जो lvalue होती है। यह निश्चित रूप से rvalue हो सकता है, लेकिन ऐसा होना आवश्यक नहीं है। और कोई अनिवार्य lvalue-to-rvalue रूपांतरण नहीं है।

मुझे यकीन नहीं है कि यह जानने में मूल्य क्या है, हालांकि।

+0

फिर भी, दिलचस्प। :) –

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