2013-01-18 12 views
5

अस्वीकरण: यह प्रश्न समझने के लिए है। मैं क्षेत्र में boost::lexical_cast का उपयोग करूंगा। It has sort of come up in the real world in places, though.क्या यह एक अस्थायी के लिए बाध्यकारी संदर्भ-से-गैर-कॉन्स का उदाहरण है?


एक "इनलाइन" लेक्स के कलाकारों दृष्टिकोण पर the following attempt लें:

#include <string> 
#include <sstream> 
#include <iostream> 

int main() 
{ 
    const std::string s = static_cast<std::ostringstream&>(
     std::ostringstream() << "hi" << 0 
    ).str(); 
    std::cout << s; 
} 

परिणाम 0x804947c0 की तरह कुछ है, क्योंकि operator<< कि "hi" साथ काम करता है एक नि: शुल्क समारोह जिसका एलएचएस लेना चाहिए std::ostream&और डैगर;, और अस्थायी std::ostringstream() एक ref-to-non-const से बाध्य नहीं हो सकता है। एकमात्र शेष मैच operator<< है जो आरएचएस और डैगर पर const void* लेता है; और डैगर;

अब let's swap the operands:

#include <string> 
#include <sstream> 
#include <iostream> 

int main() 
{ 
    const std::string s = static_cast<std::ostringstream&>(
     std::ostringstream() << 0 << "hi" 
    ).str(); 
    std::cout << s; 
} 

परिणाम "0hi" है।

यह ज्यादातर, समझ में आता है क्योंकि operator<< कि int लेता आधार ostreamऔर चाकू के एक सदस्य समारोह है, और चाकू, और कटार; और, इस तरह, अस्थायी पर बुलाए जाने के साथ ठीक है। उस ऑपरेशन का परिणाम ostream आधार का संदर्भ है, जिसके लिए अगले operator<< जंजीर है, यानी इसे (std::ostringstream() << 0) << "hi" के रूप में पढ़ें।

लेकिन फिर क्यों"hi" पर ऑपरेशन अपेक्षित परिणाम प्राप्त करने के लिए आगे बढ़ता है? क्या एलएचएस पर अभी भी एक अस्थायी संदर्भ नहीं है? सी ++ 03 पर


आइए फोकस; मुझे बताया गया है कि पहला उदाहरण वास्तविक रूप से कैल-ऑल ऑपरेटर के कारण सी ++ 11 में "इच्छित" के रूप में काम कर सकता है।

और डैगर;[C++03: 27.6.2.1]: template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,charT*);

और कटार; & कटार;[C++03: 27.6.2.1]: basic_ostream<charT,traits>& operator<<(const void* p);

और कटार; & कटार; & कटार;[C++03: 27.6.2.1]: basic_ostream<charT,traits>& operator<<(int n);

+0

मुझे लगता है कि उत्तर "सीमाओं को बाध्यकारी करने के नियमों को संदर्भित करने के नियमों के समान कुछ नहीं है; यहां पर प्रासंगिक वाक्यांश हैं"। –

+0

यह उसी कारण से काम करता है कि आप अस्थायी रूप से गैर-कॉन्स लैव्यू संदर्भों को बाध्य करने के लिए एक फ़ंक्शन टेम्पलेट 'टेम्पलेट टी & lvalue (T && v) {return v;}' लिख सकते हैं। – Mankarse

+0

क्या आपके पहले फुटनोट के लिए अधिभार नहीं होगा जो 'कॉन्स्ट चार [टी] * 'लेते हैं? (यह नहीं कि यह कुछ भी बदलता है।) – Mat

उत्तर

3

कारण सरल है। आप सवाल पढ़ अगर मैं के बारे में पूछा:

std::ostringstream printing the address of the c-string instead of its content.

आप देखेंगे कि एक अस्थायी के बजाय एक "उचित" संदर्भ प्राप्त करने के लिए चाल वस्तु पर एक विधि कॉल करने के लिए है (सीमित नहीं किसी कारण से बाध्यकारी प्रतिबंध नहीं) जो एक संदर्भ वापस करेगा।

नवाज के जवाब में ऊपर, वह std::ostream& std::ostream::flush() यहाँ कहा जाता है, आपके मामले में:

std::ostringstream() << 0 << "hi" 

आप std::ostringstream& std::ostringstream::operator<<(int) कहते हैं।

वही परिणाम।

आश्चर्यजनक व्यवहार ostream मिशमाश कार्यान्वयन के कारण है: कुछ operator<< सदस्य विधियां हैं जबकि अन्य निःशुल्क कार्य हैं।

आप इसे परीक्षण कर सकते हैं, बस, एक वस्तु पर एक X& ref() विधि को लागू करने से:

struct X { X& ref(); }; 

void call(X& x); 

int main() { 
    call(X{});  // error: cannot bind X& to a temporary 
    call(X{}.ref()); // OK 
} 

संपादित: लेकिन क्यों नहीं X& (ref के परिणाम) है ही इलाज?

यह classification का विषय है। एक अस्थायी prvalue है जबकि एक संदर्भ lvalue है। एक संदर्भ केवल lvalue से जुड़ने की अनुमति है।

बेशक

के बाद से तरीकों rvalue (और इस प्रकार prvalue) पर कहा जा सकता है और उन तरीकों वस्तुओं वे हम पर कहा जाता था के लिए एक संदर्भ वापस आ सकते हैं कर सकते हैं आसानी से बायपास मूर्खतापूर्ण (1) एक संदर्भ केवल करने के लिए बाध्य करने के लिए अनुमति दी है lvalue प्रतिबंध ...

(1) यह भी इस तथ्य के साथ असंगत है कि rvalue एक कॉन्स्ट-रेफरेंस से बंधे जा सकते हैं।

+1

मुझे नहीं लगता कि यह सवाल का जवाब देता है। मैं सदस्य समारोह और मुफ्त समारोह के बारे में जानता हूं। लेकिन ऑब्जेक्ट अभी भी एक अस्थायी है, तो संदर्भ अंत में क्यों बाध्य करता है क्योंकि इसे फ़ंक्शन कॉल द्वारा उत्पादित किया गया है? –

+0

@ लाइटनेसरेसेसिन ऑर्बिट: एक साधारण 'लवल्यू'/'रावल्यू' मुद्दा, मैंने अपना जवाब बढ़ाया। संकलक कैसे पता लगा सकता है कि 'एक्स और एक्स :: रेफरी() 'एक' एक्स' उदाहरण है जिसे 'रेफरी' कहा जाता है? यह (सामान्य रूप से) नहीं हो सकता है, इसलिए यह पूरी तरह से प्रकार के वर्गीकरण पर आधारित है। –

+0

संपादन यह करता है; धन्यवाद –

2

एलएचएस पर संदर्भ अभी भी एक अस्थायी नहीं है?

यह एक अस्थायी (वापसी मूल्य) का एक लालसा संदर्भ है, जो अभी भी एक अंतराल है और इसलिए लैवल्यू संदर्भों से जुड़ा हो सकता है।

एल/rvalueness के बजाय जीवनकाल के मामले में अस्थायी के बारे में सोचो।

+0

(आपको शायद यह पता था। मैं जो पूछ रहा हूं उससे उलझन में हूं: एस) – Pubby

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