2013-03-28 13 views
23

निम्नलिखित को ध्यान में रखते:ले जाएँ अर्थ विज्ञान और तर्क मूल्यांकन आदेश

std::string make_what_string(const std::string &id); 

struct basic_foo 
{ 
    basic_foo(std::string message, std::string id); 
}; 

struct foo 
    : public basic_foo 
{ 
    foo::foo(std::string id) 
     : basic_foo(make_what_string(id), std::move(id)) // Is this valid? 
    { 
    } 
}; 

क्योंकि सी ++ में पैरामीटर मूल्यांकन आदेश अनिर्दिष्ट है, मैं अगर सोच रहा हूँ लाइन

basic_foo(make_what_string(id), std::move(id)) 
उपरोक्त कोड में

मान्य है।

मुझे पता है कि std::move एक कलाकार से अधिक कुछ नहीं है, लेकिन std :: string कब सीटीओ निष्पादित किया जाता है? सभी तर्कों का मूल्यांकन करने के बाद और अब समय निर्माता पर कॉल करने का समय है? या यह पैरामीटर के मूल्यांकन के दौरान किया जाता है? दूसरे शब्दों में:

करता है संकलक ऐसा करते हैं:

std::string &&tmp2 = std::move(id); 
std::string tmp1 = make_what_string(id); 
basic_foo(tmp1, tmp2); 

जो वैध है। या यह:

std::string tmp2 = std::move(id); 
std::string tmp1 = make_what_string(id); 
basic_foo(tmp1, tmp2); 

जो अमान्य है। ध्यान दें कि दोनों मामलों में आदेश "अप्रत्याशित" एक है।

+0

दरअसल, कोड मान्य है। हालांकि, मेरा मानना ​​है कि आप 'base_foo' के कन्स्ट्रक्टर में स्ट्रिंग' आईडी 'को मूल्य के बजाय रैल्यू संदर्भ द्वारा लेना चाहते थे (क्या आप नहीं?)। –

+1

@CassioNeri, कोई कोड इरादा नहीं है :) – Tom

+0

हाँ, मुझे एहसास हुआ कि दोपहर के भोजन के दौरान। :-) बहुत अच्छा सवाल है। –

उत्तर

16

अनुभाग देखें 1.9:

अपवाद का उल्लेख नहीं, मूल्यांकन व्यक्तिगत ऑपरेटरों के संचालन और व्यक्तिगत अभिव्यक्तियों के उप-अभिव्यक्तियों के अपमानित हैं।

और

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

मुझे लगता है कि समस्या यह है कि यह बहुत स्पष्ट मापदंडों का आरंभीकरण तर्क भाव के साथ जुड़े एक पक्ष प्रभाव माना जाए या नहीं नहीं है। हालांकि, यह धारा 5.2.2:

प्रत्येक पैरामीटर का प्रारंभ और विनाश कॉलिंग फ़ंक्शन के संदर्भ में होता है।

और वहाँ भी एक ही पैरा में एक नोट बनाता है यह एक छोटे साफ:

एक समारोह में कहा जाता है जब, प्रत्येक पैरामीटर (8.3.5) प्रारंभ किया जाएगा (8.5, 12.8, 12.1) इसके इसी तर्क के साथ।

तो हाँ, तर्कों के प्रारंभ धुंधलेपन से एक दूसरे के लिए सम्मान के साथ अनुक्रम कर रहे हैं - [नोटअंत टिप्पणी इस तरह initializations धुंधलेपन से एक दूसरे को (1.9) के संबंध में अनुक्रम रहे हैं]। initializations इन आदेशों में से किसी में हो सकता है:

std::string message = make_what_string(id); 
std::string id = std::move(id); 

std::string id = std::move(id); 
std::string message = make_what_string(id); 

दूसरे मामले में, make_what_string के साथ काम समाप्त होता है एक में ले जाया गया-से स्ट्रिंग।

तो, भले ही std::move वास्तव में कुछ भी ले जाने नहीं है, महत्वपूर्ण बात यह है कि वास्तविक चलती भी अन्य तर्क के संबंध में unsequenced जाता है।

basic_string(basic_string&& str) राज्यों के इस कदम निर्माता की परिभाषा:

[...] str एक अनिर्दिष्ट मूल्य के साथ एक मान्य राज्य में छोड़ दिया है।

तो आपके पास अपरिभाषित व्यवहार नहीं है, आपके पास अनिर्दिष्ट व्यवहार है।

+0

@ डेविड: हां, क्योंकि स्ट्रिंग से स्थानांतरित हो सकता है, कार्यान्वयन – Tom

+0

@ टॉम वास्तव में, यह निर्दिष्ट नहीं है, अनिर्धारित नहीं है। :) –

+0

मुझे लगता है कि मानक तर्क हो सकता है: या तो पैरामीटर कॉल के पहले या बाद में पैरामीटर प्रारंभ किए जाते हैं। फ़ंक्शन कॉल के बाद असंभव है। इसलिए यह पहले होना चाहिए। और पैरामीटर प्रारंभिक रूप से कॉलर के संदर्भ में होने के लिए मानक रूप से परिभाषित किया जाता है (इसलिए इसका मूल्यांकन नहीं किया जाता है "बुलाए गए फ़ंक्शन के शरीर में")। इसलिए तर्क मूल्यांकन के संबंध में पैरामीटर प्रारंभिकरण की कोई अनुक्रमिक (और कोई संक्रमणीय अनुक्रमण नहीं है)। –

7

यह वास्तव में मान्य नहीं है। फ़ंक्शन तर्क मूल्यांकन का क्रम निर्दिष्ट नहीं है। दूसरे शब्दों में, यदि आप नहीं जानते कि क्या संकलक इस क्रम का चयन करेंगे:

tmp1 = make_what_string(id); 
tmp2 = std::move(id); 
basic_foo(tmp1, tmp2); 

या इस एक:

tmp1 = std::move(id); 
tmp2 = make_what_string(id); //id has already been moved from! 
basic_foo(tmp2, tmp1); 
+0

क्या आप निश्चित हैं? मैंने अपने प्रश्न को बेहतर तरीके से निर्दिष्ट करने के लिए अद्यतन किया है जो मैं पूछ रहा हूं। – Tom

+0

लेकिन 'std :: move' वास्तव में कुछ भी नहीं लेता है, यह केवल एक रावल्यू संदर्भ में रहता है। – interjay

+0

@interjay: दरअसल; लेकिन (जैसा कि प्रश्न वर्णन करता है) 'std :: move' * के परिणाम से फ़ंक्शन तर्क का मान बना रहा है * इसे * ले जाता है। –

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