2013-02-06 8 views
18

मैं चैट में निम्न उदाहरण में दिखाया गया था:कौन सा मानक शब्द हमें बताता है कि रीफ-टू-कॉन्स्ट अस्थायी आजीवन विस्तार केवल "एक बार काम करता है"?

#include <iostream> 
struct foo { ~foo() { std::cout << "destroying!\n"; } }; 
const foo& func(const foo& a, const foo&) { return a; } 

int main() 
{ 
    foo x; 
    const foo& y = func(foo(), x); 
    std::cout << "main\n"; 
} 

Output:

destroying! 
main 
destroying! 

यह प्रदर्शित करने के लिए कि foo अस्थायी के जीवनकाल main की सम्पूर्णता पर लागू नहीं होता दिखाई देता है, भले ही यह हो जाता है उस दायरे में एक ref-to-const तक बाध्य।

संभवतः, जीवनकाल विस्तार केवल "एक बार काम करता है"; अर्थात, यह लागू होता है जब func के तर्क शुरू किए जाते हैं, लेकिन लगातार बाइंडिंग के माध्यम से पारित नहीं किया जाता है।

क्या मेरी व्याख्या सही है? यदि ऐसा है (और यदि कोई व्यक्तिगत अनुच्छेद सीधे लागू होता है) मानक व्यवहार क्या है जो इस व्यवहार को परिभाषित करता है?

+0

'func' के लिए दूसरा तर्क क्या है? क्या होता है यदि आप इसे छोड़ देते हैं (और 'x') बंद करते हैं? –

+0

@ कोनराड रुडॉल्फ: यह टेक्स्ट '" मुख्य "के आउटपुट के सापेक्ष विनाश आदेश का प्रदर्शन करने के लिए है, मुझे लगता है। –

उत्तर

7

यह दो अंक रिपोर्ट, http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1299 और http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1568 का विषय है।

पूर्व समस्या रिपोर्ट, जिसमें से मैं संवाददाता हूं, इन सभी मामलों को कवर करने का इरादा था, जहां एक संदर्भ अस्थायी वस्तु से जुड़ा हुआ है, लेकिन इसका उद्देश्य जीवन भर में विस्तारित नहीं है। इस मुद्दे के शरीर में विवरण केवल अस्थायी अभिव्यक्तियों के साथ उलझन में आने वाले प्रावधानों का उल्लेख करता है (जो वास्तव में तय करता है कि उनका मूल्यांकन किस प्रकार किया जाता है या नहीं)। लेकिन मानक में इनके साथ अंतराल और xvalues ​​भी उलझन में हैं। एक उदाहरण जहां static_cast के संदर्भ में होता है वह मुद्दा संख्या # 1568 है (जिसमें "अस्थायी परिवर्तनीय" का उपयोग इस मामले को और भ्रमित करता है)।

वास्तव में, यह:

एक समारोह कॉल (5.2 में एक संदर्भ पैरामीटर के लिए एक अस्थायी बाध्य।2) कॉल युक्त पूर्ण अभिव्यक्ति के पूरा होने तक जारी रहता है।

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

+0

हाँ, ठीक है, आप और जेम्स ने मुझे विश्वास दिलाया है कि "छोड़कर" शब्द अनुच्छेद के नियमों को असंबद्ध नहीं करता है, क्योंकि "छोड़कर" अभी भी एक समय में एक ही परिदृश्य पर लागू किया जा रहा है, और जैसे कि दो या अधिक विरोधाभासी परिदृश्य। –

8

आप लगभग सही हैं। यह व्यवहार वास्तव में फ़ंक्शन कॉल से आता है, न कि किसी भी प्रकार के "केवल एक बार काम करता है" नियम के कारण।

इधर, पूरे जीवन भर के विस्तार "सुविधा" के लिए शब्दों है उचित नियम के साथ बोल्ड में जोर दिया:

[C++11: 12.2/5]:[..] अस्थायी करने के लिए जो संदर्भ बाध्य है या अस्थायी है कि एक subobject जो के संदर्भ में ही है की पूरी वस्तु संदर्भ के जीवन भर के लिए बनी रहती है को छोड़कर:

  • [..]
  • फ़ंक्शन कॉल (5.2.2) में संदर्भ पैरामीटर के लिए अस्थायी बाध्य कॉल युक्त पूर्ण अभिव्यक्ति को पूरा होने तक जारी रहता है।
  • [..]
+0

लेकिन इस मामले में, अस्थायी भी कॉन्स्ट संदर्भ 'y' के लिए बाध्य है। तो कौन सा संदर्भ अपने जीवनकाल को नियंत्रित करता है? –

+1

@ जेम्ससांज: मैं प्राथमिकता लेने के रूप में "छोड़कर" सूची देखता हूं। –

+0

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

3

यहाँ लागू होता है सामान्य ज्ञान है जो नियम। मानक खराब शब्द है, और वास्तव में इसकी गारंटी देता है। लेकिन इसे लागू करने के लिए व्यावहारिक तरीका नहीं है।

+0

आपका क्या मतलब है? प्रतिबंध लागू करने के लिए कोई व्यावहारिक तरीका नहीं है, या आजीवन विस्तार को लागू करने के लिए जो वर्तमान में नहीं होता है? –

+0

@ लाइटनेसरेसेसिन ऑर्बिट अस्थायी जीवनकाल को अंतिम संदर्भ में विस्तारित करने का कोई व्यावहारिक तरीका नहीं है जो इसके बाध्य है। –

+0

मुझे लगता है कि @ जेम्स मेरे उत्तर में सारांशित करने के बारे में बात कर रहा है। –

1

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

भागो इस कोड:

struct foo { 
    int id; 
    foo(int id) : id(id) { std::cout << "ctor " << id << std::endl; }; 
    ~foo() { std::cout << "dtor " << id << std::endl; } 
}; 
const foo& func(const foo& a, const foo&) { return a; } 

int main(int argc, char** argv) { 
    foo x(1); 
    const foo& y = func(foo(2), x); 
    std::cout << "main " << y.id << std::endl; 
    return 0; 
} 

उत्पादन मेरे लिए है:

ctor 1 
ctor 2 
dtor 2 
main 2 
dtor 1 

लेकिन लाइन main 2अपरिभाषित व्यवहार है।

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