2015-09-01 13 views
8

निम्नलिखित कोड snipet पर विचार के साथ जुड़े:लाइफटाइम स्थिरांक संदर्भ (विधि श्रृंखलन)

#include <iostream> 

struct S { 
    ~S() { std::cout << "dtor\n"; } 
    const S& f(int i) const { std::cout << i << "\n"; return *this; } 
}; 

int main() { 
    const S& s = S(); 
    s.f(2); 
} 

Output:

2 
dtor 

अर्थात वस्तु जीवनकाल संदर्भ द्वारा विस्तारित करता है जो हर्ब के article में समझाया गया है।

लेकिन, अगर हम कोड और लिखने की केवल एक पंक्ति बदलने के लिए: (2) पर किए गए पहले से ही नष्ट कर दिया वस्तु

const S& s = S().f(1); 

च की कॉल:

Output:

1 
dtor 
2 

क्यों क्या ऐसा हुआ? क्या एफ() का रिटर्न वैल्यू सही प्रकार का "अस्थायीता" नहीं है?

+2

'एफ' एक अंतराल नहीं, एक अंतराल देता है। –

+0

और पूर्ण विवरण के अंत में 'एस()' का जीवनकाल खत्म हो गया। – Jarod42

+0

@KerrekSB लालसा क्यों है? हम '=' के बाईं तरफ 'एफ' नहीं डाल सकते हैं। – alexolut

उत्तर

4

जब आप एक समारोह इस प्रकार लिख ...

const S& f(int i) const { std::cout << i << "\n"; return *this; } 

... आप एक const S& और आप संदर्भित वस्तु सुनिश्चित करने के लिए जिम्मेदारी ले रहे हैं वापस जाने के लिए संकलक निर्देश देते रहे हैं एक जीवन भर फोन करने वाले का के लिए उपयुक्त है उपयोग। ("सुनिश्चित करना" दस्तावेज क्लाइंट उपयोग का गठन कर सकता है जो आपके डिज़ाइन के साथ ठीक से काम करता है।)

अक्सर - हेडर और कार्यान्वयन फ़ाइलों में कोड के सामान्य पृथक्करण के साथ - f(int) const का कार्यान्वयन कोड को कॉल करने के लिए भी दिखाई नहीं देगा, और ऐसे मामलों में संकलक के पास S संबंधित कोई संदर्भ नहीं है, और न ही S एक अस्थायी है या नहीं, इसलिए इसका कोई आधार नहीं है कि यह तय करने के लिए कि जीवनकाल को विस्तारित करने की आवश्यकता है या नहीं।

साथ ही स्पष्ट विकल्प (उदा। ग्राहकों को सुरक्षित कोड लिखने, मूल्य या स्मार्ट सूचक द्वारा लौटने पर भरोसा करना), यह एक अधिक अस्पष्ट विकल्प के बारे में जानने योग्य है ...

const S& f(int i) const & { ...; return *this; } 
const S f(int i) const && { ...; return *this; } 

& और && ठीक पहले समारोह निकायों को ओवरलोड f ऐसी है कि && संस्करण यदि *this चल रहा है प्रयोग किया जाता है, अन्यथा & संस्करण का उपयोग किया जाता है। इस तरह, कोई const & से f(...) को बाध्यकारी ऑब्जेक्ट पर बुलाया जाता है, ऑब्जेक्ट की एक नई प्रतिलिपि से जुड़ा होगा और स्थानीय const संदर्भ के अनुसार जीवनकाल बढ़ाया जाएगा, जबकि जब वस्तु समाप्त नहीं हो रही है (अभी तक) const संदर्भ होगा मूल वस्तु (जिसे अभी भी संदर्भ के रूप में लंबे समय तक गारंटी नहीं दी जाती है - कुछ सावधानी बरतनी चाहिए)।

+0

क्या आपके पास कोई फ़ंक्शन संदर्भ देने के मामले में कोड को और अधिक सुरक्षित लिखने की कोई सिफारिश है? शायद इसे मूल्य के लिए असाइन किया जा सकता है (कोई अन्य संदर्भ नहीं)? आदर्श रूप में, यह त्रुटि संकलन-समय पर होती है। – alexolut

+0

@alexolut वर्तमान में, सबसे अच्छा अनुशंसा सी ++ में विधि श्रृंखला का उपयोग नहीं करना है। यह भी ध्यान रखें कि मूल्यांकन का आदेश अनिर्दिष्ट है, इसलिए 'foo.f (bar()) .g (baz())' में, आप 'bar()' से पहले 'baz()' कहला सकते हैं। – Potatoswatter

+0

@alexolut: मैंने कुछ विकल्पों पर चर्चा के उत्तर में कुछ जोड़ा है। –

3

ऐसा क्यों हुआ? f() का रिटर्न वैल्यू सही प्रकार का "अस्थायीता" नहीं है?

ठीक है, यह नहीं है। यह हाल ही में कुछ हद तक विवादास्पद मुद्दा है: "अस्थायीता" की आधिकारिक परिभाषा कुछ हद तक खुली है।

हाल के कंपाइलरों में, अस्थायीता बढ़ रही है। सबसे पहले यह केवल प्रवाल (गैर- "संदर्भ") अभिव्यक्तियों पर लागू होता है, और सदस्य इस तरह के अभिव्यक्तियों पर लागू ("डॉट ऑपरेटर") एक्सेस करता है। अब यह कास्ट एक्सप्रेशन और सरणी एक्सेस पर भी लागू होता है। यद्यपि आप static_cast< T && >(t) के रूप में एक चाल ऑपरेशन लिख सकते हैं, जो अस्थायीता को संरक्षित रखेगा, बस std::move(t) लिखना नहीं होगा।

मैं proposals के series पर सी ++ का विस्तार करने के लिए काम कर रहा हूं, इसलिए आपका उदाहरण आपके अपेक्षित काम करेगा। कुछ nonzero मौका है कि सुविधा सी ++ 17 में दिखाई दे सकता है।

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