2010-04-10 11 views
8

"यदि आप फ़ंक्शन से कोई मान (संदर्भ नहीं) वापस करते हैं, तो इसे कॉलिंग फ़ंक्शन में एक कॉन्स्ट संदर्भ में बाध्य करें, इसका जीवनकाल कॉलिंग फ़ंक्शन के दायरे तक बढ़ाया जाएगा।"कॉलिंग फ़ंक्शन में किसी कॉन्स संदर्भ के लिए बाध्य होने पर कॉलिंग फ़ंक्शन के दायरे में विस्तारित मूल्य का उसका जीवनकाल कैसा रहता है?

तो: मामला एक

const BoundingBox Player::GetBoundingBox(void) 
{ 
    return BoundingBox(&GetBoundingSphere()); 
} 

समारोह से प्रकार const BoundingBox का मान देता है GetBoundingBox()

संस्करण मैं: संस्करण द्वितीय (यह बाइंड एक स्थिरांक संदर्भ के लिए)

const BoundingBox& l_Bbox = l_pPlayer->GetBoundingBox(); 

: (इसे एक कॉन्स कॉपी से बांधें)

const BoundingBox l_Bbox = l_pPlayer->GetBoundingBox(); 

दोनों ठीक काम करते हैं और मुझे l_Bbox ऑब्जेक्ट को दायरे से बाहर नहीं देखा जाता है। (हालांकि, मैं एक प्रकार में समझता हूं, कॉपी कन्स्ट्रक्टर नहीं कहा जाता है और इस प्रकार संस्करण II से थोड़ा बेहतर है)।

इसके अलावा, तुलना के लिए, मैंने निम्नलिखित परिवर्तन किए हैं।

मामला बी

BoundingBox Player::GetBoundingBox(void) 
{ 
    return BoundingBox(&GetBoundingSphere()); 
} 
प्रकार के साथ

: मैं

BoundingBox& l_Bbox = l_pPlayer->GetBoundingBox(); 

और द्वितीय:

BoundingBox l_Bbox = l_pPlayer->GetBoundingBox(); 

वस्तु l_Bbox अभी भी गुंजाइश बाहर जाना नहीं है। कॉलिंग फ़ंक्शन में इसे एक कॉन्स्ट संदर्भ में कैसे बांधता है, इसका जीवनकाल कॉलिंग फ़ंक्शन के दायरे तक बढ़ाया जाएगा ", वास्तव में ऑब्जेक्ट का जीवनकाल कॉलिंग फ़ंक्शन के दायरे में बढ़ाता है?

क्या मुझे यहां कुछ मामूली याद आ रही है?

+1

तथ्य यह है कि यह आपके विशिष्ट कंपाइलर (जो है, बीटीडब्ल्यू ...?) पर काम करने लगता है इसका मतलब यह नहीं है कि यह किसी अन्य कंपाइलर पर काम करने जा रहा है, न कि यह अच्छी तरह से परिभाषित और कानूनी है। –

+0

@ पीटर: मैं एमएसवीसी 2008 का उपयोग कर रहा हूं। मुझे क्या बच निकलता है क्यों/जीवनकाल को विस्तारित करने पर कोई प्रभाव नहीं पड़ सकता है। मेरी राय में, यह किसी को वस्तु (कॉन्स शुद्धता इत्यादि) में परिवर्तन करने से रोकता है और यह है .. – brainydexter

+1

आपका संस्करण मैं थोड़ा मजाकिया दिखता हूं - क्या आपका कंपाइलर वास्तव में शिकायत के बिना स्वीकार करता है?ऐसा लगता है कि आप एक रावल्यू के साथ गैर-कॉन्स के संदर्भ को प्रारंभ कर रहे हैं, जिसे अनुमति नहीं दी जानी चाहिए। –

उत्तर

8

आम तौर पर एक अस्थायी वस्तु (एक एक समारोह कॉल द्वारा लौटाए गए इस तरह के रूप में) एक जीवन भर है कि "संलग्न अभिव्यक्ति" के अंत तक फैली हुई है। हालांकि, संदर्भ के लिए एक अस्थायी बाध्यता आमतौर पर संदर्भ के जीवनकाल में (जिसे कॉलिंग फ़ंक्शन का जीवनकाल हो सकता है) हो सकता है, लेकिन कुछ अपवाद हैं।

को जो संदर्भ ही है अस्थायी या अस्थायी एक subobject जिनमें से अस्थायी जीवन भर के लिए बनी ही है करने के लिए पूरी वस्तु है कि: यह 12.2/5 "अस्थाई वस्तुओं" में मानक से आच्छादित है नीचे निर्दिष्ट के रूप में संदर्भ के संदर्भ में। एक कन्स्ट्रक्टर के सीटीओ-प्रारंभकर्ता (12.6.2) में एक संदर्भ सदस्य के लिए एक अस्थायी बाध्य जब तक कि निर्माता बाहर निकलता रहता है। फ़ंक्शन कॉल (5.2.2) में संदर्भ पैरामीटर के लिए अस्थायी बाध्य कॉल युक्त पूर्ण अभिव्यक्ति को पूरा होने तक जारी रहता है।

एक उदाहरण है कि कल्पना क्या हो रहा है मदद कर सकता है:

#include <iostream> 
#include <string> 

class foo { 
public: 
    foo(std::string const& n) : name(n) { 
     std::cout << "foo ctor - " << name + " created\n"; 
    }; 
    foo(foo const& other) : name(other.name + " copy") { 
     std::cout << "foo copy ctor - " << name + " created\n"; 
    }; 

    ~foo() { 
     std::cout << name + " destroyed\n"; 
    }; 

    std::string getname() const { return name; }; 
    foo getcopy() const { return foo(*this); }; 

private: 
    std::string name; 
}; 

std::ostream& operator<<(std::ostream& strm, foo const& f) { 
    strm << f.getname(); 
    return strm; 
} 


int main() 
{ 
    foo x("x"); 

    std::cout << x.getcopy() << std::endl; 

    std::cout << "note that the temp has already been destroyed\n\n\n"; 

    foo const& ref(x.getcopy()); 

    std::cout << ref << std::endl; 

    std::cout << "the temp won't be deleted until after this...\n\n"; 
    std::cout << "note that the temp has *not* been destroyed yet...\n\n"; 
} 

Whi

अधिक जानकारी के लिए निम्न देखें ch प्रदर्शित करता है:

foo ctor - x created 
foo copy ctor - x copy created 
x copy 
x copy destroyed 
note that the temp has already been destroyed 


foo copy ctor - x copy created 
x copy 
the temp won't be deleted until after this... 

note that the temp has *not* been destroyed yet... 

x copy destroyed 
x destroyed 
2

बिंदु यह है कि मूल्य से लौटने पर, मान पर कॉपी किया गया है जिसमें आप फ़ंक्शन का परिणाम निर्दिष्ट कर रहे हैं। (जैसे आपने कहा - कॉपी कन्स्ट्रक्टर कहा जाता है)। कोई आजीवन विस्तार नहीं, आप बस एक नई वस्तु बनाते हैं।

संदर्भ द्वारा लौटने पर, हुड के नीचे आप केवल फ़ंक्शन में परिभाषित चर के लिए पॉइंटर पास करते हैं। इसलिए, एक नई वस्तु नहीं बनाई गई है, तो आप केवल फ़ंक्शन के बाहर इसका संदर्भ लेते हैं। उस मामले के साथ एक समारोह-अंदर परिवर्तनीय का जीवनकाल बढ़ाया गया है।

1

आमतौर पर, यदि आप एक समारोह से मूल्य से एक ऑब्जेक्ट ने कहा कि वस्तु नष्ट हो जाएगा जब काम अभिव्यक्ति समाप्त हो गया है:

myclass X = getX(); // after copy constructor, the returned value is destroyed 
        // (but you still hold a copy in X) 

मामले आपके द्वारा बताई में, दिए गए मान बाद में नष्ट कर दिया जाएगा पर, आप इसे उपयोग करने की अनुमति:

const myclass& X = getX(); 
cout << X.a << endl; // still can access the returned value, it's not destroyed 
4

सबसे पहले, अस्थायी वस्तु के जीवनकाल स्थिरांक संदर्भ के जीवनकाल है कि यह करने के लिए बाध्य कर रहा है, के लिए बढ़ा हो जाता है नहीं है (हालांकि शायद कि क्या आपको लगता है कि अजीब से मतलब था "बुला समारोह के दायरे करने के लिए" शब्द "कॉलिंग फ़ंक्शन का दायरा")। यह आपके CASE A दिखाता है, जहां आप अस्थायी के संदर्भ में const संलग्न करते हैं। जब तक संदर्भ रहता है तब तक अस्थायी रहना जारी रहता है। जब संदर्भ अपने जीवनकाल को समाप्त करता है, तो अस्थायी वस्तु भी नष्ट हो जाती है।

दूसरा, आपका CASE B बस बीमार, गैर-संगत है। अर्थात्,

BoundingBox& l_Bbox = l_pPlayer->GetBoundingBox(); 

अवैध है। अस्थायी के लिए गैर-कॉन्स्ट संदर्भ को संलग्न करने के लिए सी ++ में अवैध है। यदि आपका कंपाइलर इसे अनुमति देता है, तो यह आपके कंपाइलर का क्विर्क/एक्सटेंशन होना चाहिए, जो सी ++ भाषा के साथ बहुत कम नहीं है।