c++ - कब्जे से अपरिभाषित व्यवहार द्वारा एक नवनिर्मित वस्तु पर कब्जा कर रहा है




c++11 const (4)

निम्नलिखित (विपरीत उदाहरण) ठीक है या क्या यह अपरिभाषित व्यवहार है:

// undefined behavior?
const auto& c = SomeClass{};

// use c in code later
const auto& v = c.GetSomeVariable();

यह इस विशिष्ट मामले में सुरक्षित है। ध्यान दें कि सभी अस्थायी नक्षत्रों को कब्जे में लेने के लिए सुरक्षित नहीं है ... उदाहरण के लिए

#include <stdio.h>

struct Foo {
    int member;

    Foo() : member(0) {
        printf("Constructor\n");
    }

    ~Foo() {
        printf("Destructor\n");
    }

    const Foo& method() const {
        return *this;
    }
};

int main() {
    {
        const Foo& x = Foo{};        // safe
        printf("here!\n");
    }
    {
        const int& y = Foo{}.member; // safe too (special rule for this)
        printf("here (2)!\n");
    }
    {
        const Foo& z = Foo{}.method(); // NOT safe
        printf("here (3)!\n");
    }
    return 0;
}

z लिए प्राप्त संदर्भ उपयोग करने के लिए सुरक्षित नहीं है क्योंकि printf स्टेटमेंट तक पहुंचने से पहले अस्थायी उदाहरण को पूर्ण अभिव्यक्ति के अंत में नष्ट कर दिया जाएगा। आउटपुट है:

Constructor
here!
Destructor
Constructor
here (2)!
Destructor
Constructor
Destructor
here (3)!

यह सुरक्षित है। कांस्ट रेफरी अस्थायी के जीवनकाल को लम्बा खींचता है। दायरा कॉन्स्टेंट रिफ का दायरा होगा।

एक अस्थायी वस्तु के lifetime को कास्ट लैवल्यू रेफ़रेंस से या किसी रेवल्यू रेफ़रेंस (C ++ 11 के बाद से) के लिए बढ़ाया जा सकता है, विवरण के लिए संदर्भ इनिशियलाइज़ेशन देखें।

जब भी एक संदर्भ एक अस्थायी या उसके अधीन होने के लिए बाध्य होता है, तो अस्थायी का जीवनकाल निम्नलिखित अपवादों के साथ संदर्भ के जीवनकाल से मेल खाने के लिए बढ़ाया जाता है :

  • रिटर्न स्टेटमेंट में किसी फ़ंक्शन के रिटर्न मान के लिए एक अस्थायी सीमा को विस्तारित नहीं किया जाता है: यह रिटर्न एक्सप्रेशन के अंत में तुरंत नष्ट हो जाता है। इस तरह के फ़ंक्शन हमेशा एक झूलने वाला संदर्भ देता है।
  • कंस्ट्रक्टर इनिशियलाइज़र सूची में एक संदर्भ सदस्य के लिए एक अस्थायी बाध्य केवल तब तक बनी रहती है जब तक कि कंस्ट्रक्टर बाहर नहीं निकलता है, जब तक कि ऑब्जेक्ट मौजूद नहीं है। (नोट: इस तरह की इनिशियलाइज़ेशन DR 1696 के रूप में बीमार है)।
  • एक फंक्शन कॉल में एक रेफरेंस पैरामीटर के लिए एक अस्थायी बाध्य, फंक्शन एक्सप्रेशन वाले पूर्ण एक्सप्रेशन के अंत तक मौजूद होता है: यदि फंक्शन एक रेफरेंस देता है, जो फुल एक्सप्रेशन को आउटलाइव करता है, तो यह एक झूलने वाला रेफरेंस बन जाता है।
  • एक नए-अभिव्यक्ति में प्रयुक्त इनिशियलाइज़र में एक संदर्भ के लिए एक अस्थायी बाध्य, उस नई-अभिव्यक्ति वाले पूर्ण अभिव्यक्ति के अंत तक मौजूद है, जब तक कि प्रारंभिक ऑब्जेक्ट के रूप में नहीं। यदि आरंभिक वस्तु पूर्ण अभिव्यक्ति को रेखांकित करती है, तो इसका संदर्भ सदस्य एक झूलने वाला संदर्भ बन जाता है।
  • सूची-आरंभीकरण सिंटैक्स (ब्रेसिज़) का उपयोग करते हुए प्रत्यक्ष-आरंभीकरण सिंटैक्स (कोष्ठक) का उपयोग करते हुए एक प्रारंभिक प्रारंभिक के संदर्भ तत्व में एक संदर्भ के लिए एक अस्थायी बाध्य, इनिशियलाइज़र युक्त पूर्ण अभिव्यक्ति के अंत तक मौजूद है। struct A { int&& r; }; A a1{7}; // OK, lifetime is extended A a2(7); // well-formed, but dangling reference

सामान्य तौर पर, अस्थायी के जीवनकाल को "इसे पास करके" आगे नहीं बढ़ाया जा सकता है: एक दूसरा संदर्भ, जिस संदर्भ से अस्थायी बाध्य था, उसके जीवनकाल को प्रभावित नहीं करता है।

जैसा @ कोनराड रूडोल्फ ने बताया (और ऊपर का अंतिम पैराग्राफ देखें):

"यदि c.GetSomeVariable() एक स्थानीय वस्तु का संदर्भ देता है या एक संदर्भ है कि यह स्वयं किसी वस्तु के जीवनकाल का विस्तार कर रहा है, तो आजीवन विस्तार किक नहीं करता है"


हां यह पूरी तरह से सुरक्षित है: एक const संदर्भ के लिए बंधन अस्थायी के जीवनकाल को उस संदर्भ के दायरे तक बढ़ाता है।

ध्यान दें कि व्यवहार हालांकि सकर्मक नहीं है। उदाहरण के लिए, साथ

const auto& cc = []{
    const auto& c = SomeClass{};
    return c;
}();

cc खतरे


यह सुरक्षित है।

[class.temporary]/5 : तीन संदर्भ हैं जिनमें पूर्ण अभिव्यक्ति के अंत की तुलना में एक अलग बिंदु पर अस्थायी रूप से नष्ट हो जाते हैं। [..]

[class.temporary]/6 : तीसरा संदर्भ वह है जब कोई संदर्भ किसी अस्थायी वस्तु से जुड़ा हो। वह अस्थायी वस्तु जिसके संदर्भ में सीमा बंधी हो या अस्थायी वस्तु जो किसी उप-विषय की पूरी वस्तु है, जिसके संदर्भ में संदर्भ बंधा हुआ है, संदर्भ के आजीवन के लिए बनी रहती है यदि संदर्भ जिसमें से बाध्य है संदर्भ निम्न में से एक के माध्यम से प्राप्त किया गया था : [यहाँ बहुत सारी चीजें]





undefined-behavior