C++-एक अस्थायी, ठीक या यूबी के सदस्य को लम्बा करने के लिए कॉन्स्ट रेफरेंस का उपयोग करना?




language-lawyer lifetime (2)

कुछ इस तरह से विचार करें:

#include <iostream>

struct C {
    C(double x=0, double y=0): x(x) , y(y) {
        std::cout << "C ctor " << x << " " <<y << " "  << "\n";
    }
    double x, y;
};

struct B {
    B(double x=0, double y=0): x(x), y(y) {}
    double x, y;
};

struct A {
    B b[12];

    A() {
        b[2] = B(2.5, 14);
        b[4] = B(56.32,11.99);
    }
};


int main() {
    const B& b = A().b[4];
    C c(b.x, b.y);
}

जब मैं -O0 के साथ संकलित करता हूं तो मुझे प्रिंट मिल रहा है

C ctor 56.32 11.99

लेकिन जब मैं -O2 के साथ संकलन करता हूं तो मुझे मिल रहा है

 C ctor 0 0

मुझे पता है कि हम स्थानीय अस्थायी को लंबा करने के लिए कॉन्स्ट रेफरेंस का उपयोग कर सकते हैं, इसलिए कुछ ऐसा है

const A& a = A();
const B& b = a.b;

पूरी तरह से कानूनी होगा। लेकिन मैं तर्क के लिए संघर्ष कर रहा हूं कि किसी भी प्रकार के अस्थायी के लिए एक ही तंत्र / नियम क्यों लागू नहीं होता है

भविष्य के संदर्भ के लिए संपादित करें:

मैं gcc संस्करण 6.3.0 का उपयोग कर रहा हूँ


आपका कोड अच्छी तरह से बनाया जाना चाहिए, क्योंकि temporaries

(जोर मेरा)

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

दिया गया A().b[4] , b[4] का उप-बिंदु है और डेटा सदस्य b , temproray A() का उप-विषय है, जिसका जीवनकाल बढ़ाया जाना चाहिए।

-O2 के साथ clang10 पर रहते हैं
-O2 के साथ gcc10 पर रहते हैं

BTW: यह एक gcc का bug प्रतीत होता है जिसे ठीक कर दिया गया है।

मानक से, [class.temporary]/6

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

...

[ उदाहरण:

template<typename T> using id = T;

int i = 1;
int&& a = id<int[3]>{1, 2, 3}[i];          // temporary array has same lifetime as a
const int& b = static_cast<const int&>(0); // temporary int has same lifetime as b
int&& c = cond ? id<int[3]>{1, 2, 3}[i] : static_cast<int&&>(0);
                                           // exactly one of the two temporaries is lifetime-extended

- अंतिम उदाहरण]


ए ()। बी [4] एक अस्थायी या प्रतिद्वंद्विता नहीं है, यही वजह है कि यह काम नहीं करता है। जब तक ए () एक अस्थायी है, आप एक सरणी तत्व का संदर्भ बना रहे हैं जो निर्माण के बिंदु पर मौजूद है। Dtor तब A () के लिए ट्रिगर होता है, जिसका अर्थ है कि बाद में bb तक पहुंच कुछ अपरिभाषित व्यवहार बन जाता है। आपको यह सुनिश्चित करने के लिए ए और होल्ड पर रहना होगा कि बी वैध है।

    const A& a = A();
    const B& b = a.b[4];
    C c(b.x, b.y);






reference-binding