2016-02-13 8 views
7
class Test { 

public: 

    int n1; 

}; 

Test func() { 

    return Test(); 

} 

int main() { 

    func() = Test(); 

} 

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

मुझे पता है कि अंतराल स्मृति में एक जगह है, तो क्या यह कार्य एक अस्थायी अंतराल (रावल्यू?) बना रहा है और इसे किसी अन्य अंतराल को सौंपा गया है? क्या कोई यह समझा सकता है कि यह वाक्यविन्यास कैसे काम करता है?

+0

यह नहीं है "_If एक समारोह एक rvalue_ रिटर्न"। – curiousguy

उत्तर

6

फ़ंक्शन कॉल अभिव्यक्ति की मान श्रेणी वास्तव में एक रावल्यू है।

दरअसल, आप प्रतिलिपि प्राइमेटिव्स पर कॉपी असाइनमेंट ऑपरेटर को कॉल नहीं कर सकते हैं। सी में राजस्व की ऐतिहासिक परिभाषा वास्तव में भेद था कि वे एक अभिप्राय के बाईं ओर नहीं हो सकते हैं।

कक्षाओं के असाइनमेंट ऑपरेटर थोड़ा अलग हैं, हालांकि। वे नियमित सदस्य कार्य हैं। और कोई नियम राजस्व के सदस्य कार्यों को कॉल करने से रोकता है। दरअसल, जब कार्यों के साइड इफेक्ट होते हैं तो यह अक्सर काफी उपयोगी होता है।

यह कैसे काम करता है, ठीक है, कॉपी असाइनमेंट ऑपरेटर को अस्थायी पर बुलाया जाता है, ऑपरेटर अस्थायी स्थिति को बदलकर सही हाथ तर्क की प्रतिलिपि बनाता है। बयान के बाद, अस्थायी वस्तु को त्याग दिया जाता है। कोई यूबी नहीं है, बस व्यर्थ प्रतिलिपि है।

आप ऑपरेटर को संदर्भ क्वालीफायर के साथ घोषित करके, एक रावल्यू पर प्रतिलिपि को कॉपी करने से रोक सकते हैं: Test& operator=(Test) & = default;। रेफ-क्वालीफायर केवल बाद में सी ++ 11 में जोड़े गए थे, इसलिए (निहित) कॉपी असाइनमेंट को पहले से अर्हता प्राप्त करने के लिए निर्दिष्ट नहीं किया जा सका। संभवतः, सी ++ 11 ने पुराने कोड को तोड़ने से रोकने के लिए निहित प्रतिलिपि निर्माता के क्वालीफायर को नहीं बदला है, जो कि इस तरह के असाइनमेंट को काफी व्यर्थ लगता है। High Integrity C++ Coding Standard अनुशंसा करता है कि आप उपयोगकर्ता परिभाषित प्रति असाइनमेंट ऑपरेटरों के साथ रेफ क्वालीफायर का उपयोग करें।

+0

"_ फ़ंक्शन का वापसी मूल्य वास्तव में एक rvalue._" नहीं, लौटाया गया ऑब्जेक्ट एक ऑब्जेक्ट है। – curiousguy

+1

@curiousguy ऑब्जेक्ट एक्सप्रेशन में मूल्य श्रेणियां हैं। इस मामले में श्रेणी आर मूल्य है। – user2079303

+0

सभी अभिव्यक्तियों में श्रेणियां हैं, न कि केवल एक वस्तु का संदर्भ देने वाले। लौटाया गया वस्तु सिर्फ एक वस्तु है, अभिव्यक्ति नहीं। – curiousguy

1

value categories तक एक बहुत सीधी सीखने की वक्र है (कम से कम मेरे लिए), लेकिन मेरा मानना ​​है कि आपको अपने उदाहरण पर terminology मिल गया है। तो

func() 

वास्तव में एक prvalue और सी ++ स्टैंडर्ड सममूल्य से वापस आती है। 3.10.5 (मैं केवल वर्तमान draft, अपने पैरा संख्या अलग-अलग हो सकता है) हम पढ़ें:

एक वस्तु के लिए एक lvalue आदेश है कि को छोड़कर वर्ग प्रकार का एक rvalue वस्तु को संशोधित करने के लिए आवश्यक है कर सकते हैं कुछ परिस्थितियों में के तहत अपने संदर्भ को संशोधित करने के लिए भी इस्तेमाल किया जाए। [उदाहरण: ऑब्जेक्ट (9.3) के लिए बुलाया गया एक सदस्य फ़ंक्शन ऑब्जेक्ट को संशोधित कर सकता है। - अंत उदाहरण]

तो असाइनमेंट ऑपरेटर, जो एक सदस्य कार्य है, मानक में उल्लिखित उदाहरण में, नियमों का अपवाद है, जिससे राजस्व में संशोधन किया जा सकता है।

(हाँ, चीनी लेपित मौत जाल, तुम अनजान चियरलीडर्स:

यह इस C++ FQA अंश अपने सबसे चरम उदाहरण के साथ प्रोग्रामिंग दुनिया में काफी आलोचना को जन्म दिया है,।X& obj=a.b().c() - ओओएस, b() एक अस्थायी वस्तु है और सी() इसमें एक संदर्भ देता है! किसी संदर्भ को असाइन नहीं किया जाना चाहिए था। । एक संकलक चेतावनी के लिए कई नहीं संभावना है, या तो)

लेकिन असली C++ प्रोग्रामिंग यह industrial applicationsnamed parameter मुहावरा की तरह है:

std::cout << X::create().setA(10).setB('Z') << std::endl; 
+0

आपको शब्दावली गलत मिली: फ़ंक्शन कॉल 'func() 'एक रावल्यू है, वापसी मान नहीं है। – curiousguy

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