C ++ फ़ंक्शन मापदंडों में मूल्यांकन का क्रम


90

यदि हमारे पास तीन कार्य (फू, बार और बाज) हैं जो इस तरह से बनाये गए हैं ...

foo(bar(), baz())

क्या सी ++ मानक द्वारा कोई गारंटी है कि बार का मूल्यांकन बाज से पहले किया जाएगा?

जवाबों:


102

नहीं, ऐसी कोई गारंटी नहीं है। यह C ++ मानक के अनुसार अनिर्दिष्ट है।

बज़्ने स्ट्रॉस्ट्रुप ने यह भी स्पष्ट रूप से "द सी ++ प्रोग्रामिंग लैंग्वेज" तृतीय संस्करण खंड 6.2.2 में, कुछ कारण के साथ स्पष्ट रूप से कहा है:

अभिव्यक्ति मूल्यांकन आदेश पर प्रतिबंध के अभाव में बेहतर कोड उत्पन्न किया जा सकता है

यद्यपि तकनीकी रूप से यह उसी खंड के पहले भाग को संदर्भित करता है जो कहता है कि किसी अभिव्यक्ति के कुछ हिस्सों के मूल्यांकन का क्रम भी अनिर्दिष्ट है, अर्थात

int x = f(2) + g(3);   // unspecified whether f() or g() is called first

मैं 8 मिनट में इस उत्तर को स्वीकार कर सकता हूं ... मुझे लगता है कि मैं थोड़ा सा घेर रहा हूं!
क्लार्क गैबेल

4
हां, लेकिन बेहतर कोड WRITTEN (= क्लीनर) हो सकता है यदि अभिव्यक्ति मूल्यांकन आदेश STRICT था, जो आमतौर पर कोड पीढ़ी की तुलना में बहुत अधिक महत्वपूर्ण है। इस उदाहरण को देखें: stackoverflow.com/questions/43612592/… तो वहाँ, स्ट्रॉस्ट्रुप।
बिल कोटियास

1
यदि आदेश देने वाले मामले आप स्वयं अनुक्रमण करने के लिए स्वतंत्र हैं। अन्यथा ऐसा करने के लिए हमेशा एक ऐसी चीज की कीमत चुकानी होगी जो हमेशा (शायद ही कभी?) मायने नहीं रखती। मुझे लगता है कि जो आप उपयोग नहीं करते हैं उसके लिए भुगतान न करने की नीति केवल एक चीज है जो अधिकांश सी ++ प्रोग्रामर सहमत हैं।
tweej

3
क्या "अनिर्धारित" के बजाय "अनिर्दिष्ट व्यवहार" नहीं होना चाहिए?
GoodDeeds

1
@ChrisDodd ने "अपरिभाषित" बनाम "अनिर्दिष्ट" शब्द का उपयोग करने के कारण एक स्वीकृत उत्तर को अस्वीकार कर दिया, मेरे लिए दुर्भावनापूर्ण पदावली की तरह लगता है ... मैंने यह नहीं कहा कि यह "अपरिभाषित व्यवहार" है, और अन्यथा और "अपरिभाषित" और "अनिर्दिष्ट" प्रतीत होते हैं। पर्याय बन गया? किसी भी मामले में, उत्तर को संपादित करने का प्रस्ताव इस पर चर्चा करने के लिए एक अधिक उत्पादक तरीका होगा
एली बेंडरस्की

20

बार () और बाज () के लिए कोई निर्दिष्ट आदेश नहीं है - मानक केवल यही कहता है कि वे दोनों का मूल्यांकन फू () से पहले किया जाएगा। C ++ मानक से, खंड 5.2.2 / 8:

तर्कों के मूल्यांकन का क्रम अनिर्दिष्ट है।


4
तथ्य यह है कि वे फू () से पहले मूल्यांकन कर रहे हैं थोड़ा आश्वस्त है, कम से कम।
बिल कोट्सियास

1
@BillKotsias मानक यह भी कहता है कि फ़ंक्शन कॉल ओवरलैप नहीं हो सकती हैं (यानी एक कार्यान्वयन लाइन 1 की नहीं चल सकती है bar, फिर लाइन 1 की baz, फिर लाइन 2 की bar, आदि), जो भी अच्छा है। :-)
मेलपोमीन

20

[5.2.2] फंक्शन कॉल से,

तर्कों के मूल्यांकन का क्रम अनिर्दिष्ट है। फ़ंक्शन में प्रवेश करने से पहले तर्क अभिव्यक्ति मूल्यांकन के सभी दुष्प्रभाव।

इसलिए, इस बात की कोई गारंटी नहीं है कि bar()पहले चलेगा baz(), केवल वही bar()और baz()पहले कहा जाएगा foo

यह भी नोट करें:

को छोड़कर, जहां उल्लेख किया गया [जैसे विशेष नियम &&और ||], अलग-अलग संचालकों के संचालन के मूल्यांकन का क्रम और व्यक्तिगत अभिव्यक्तियों के उपप्रकार, और जिस क्रम में दुष्प्रभाव होते हैं, वह अनिर्दिष्ट है।

इसलिए भले ही आप चाहे पूछ रहे थे bar()पहले चलेंगे baz()में foo(bar() + baz()), आदेश अभी भी अनिर्दिष्ट है।


4
[५.१४] से एक "विशेष नोट" का एक उदाहरण तार्किक और ऑपरेटर: "इसके विपरीत &, &&बाएं से दाएं मूल्यांकन की गारंटी देता है: दूसरे ऑपरेंड का मूल्यांकन नहीं किया जाता है यदि पहला ऑपरेंड है false।"
डैनियल ट्रेबिएन

11

C ++ 17 ऑपरेटरों के लिए मूल्यांकन आदेश को निर्दिष्ट करता है जो C ++ 17 तक अनिर्दिष्ट था। प्रश्न देखें C ++ 17 द्वारा प्रस्तुत मूल्यांकन आदेश गारंटी क्या हैं? लेकिन अपनी अभिव्यक्ति पर ध्यान दें

foo(bar(), baz())

अभी भी अनिर्दिष्ट मूल्यांकन आदेश है।


2

C ++ 11 में, संबंधित पाठ 8.3.6 डिफ़ॉल्ट तर्क / 9 (जोर मेरा) में पाया जा सकता है

हर बार फ़ंक्शन को कॉल करने पर डिफ़ॉल्ट तर्कों का मूल्यांकन किया जाता है। फ़ंक्शन तर्कों के मूल्यांकन का क्रम अनिर्दिष्ट है । नतीजतन, एक फ़ंक्शन के मापदंडों का उपयोग डिफ़ॉल्ट तर्क में नहीं किया जाएगा, भले ही उनका मूल्यांकन न किया जाए।

उसी क्रिया का उपयोग C ++ 14 मानक के रूप में भी किया जाता है, और उसी अनुभाग के अंतर्गत पाया जाता है


0

जैसा कि दूसरों ने पहले ही बताया है, मानक इस विशेष परिदृश्य के लिए मूल्यांकन के आदेश पर कोई मार्गदर्शन नहीं देता है। मूल्यांकन का यह क्रम तब संकलक के पास छोड़ दिया जाता है, और संकलक के पास गारंटी हो सकती है।

यह याद रखना महत्वपूर्ण है कि सी ++ मानक वास्तव में असेंबली / मशीन कोड के निर्माण पर संकलक को निर्देश देने के लिए एक भाषा है। मानक समीकरण का केवल एक हिस्सा है। जहां मानक अस्पष्ट है या विशेष रूप से कार्यान्वयन परिभाषित किया गया है, आपको संकलक की ओर मुड़ना चाहिए और यह समझना चाहिए कि यह C ++ निर्देशों को सही मशीन भाषा में कैसे अनुवाद करता है।

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

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