2012-03-02 15 views
21

मुझे पता है कि यह आम तौर पर std::move साथ वापस जाने के लिए एक अच्छा विचार नहीं है हूँ, अर्थातएकाधिक रिटर्न स्टेटमेंट के मामले में 'std :: move` समझदार के साथ वापस आ रहा है?

bigObject foo() { bigObject result; /*...*/ return std::move(result); } 
बजाय बस

bigObject foo() { bigObject result; /*...*/ return result; } 

क्योंकि यह वापसी मान अनुकूलन के रास्ते में हो जाता है। लेकिन

 return std::move(result); 
में कई अलग अलग रिटर्न के साथ एक समारोह, विशेष रूप से की तरह

class bar { 
    bigObject fixed_ret; 
    bool use_fixed_ret; 
    void prepare_object(bigObject&); 
public: 
    bigObject foo() { 
    if(use_fixed_ret) 
     return fixed_ret; 
    else{ 
     bigObject result; 
     prepare_object(result); 
     return result; 
    } 
    } 
}; 

मुझे लगता है कि सामान्य वापसी मान अनुकूलन इस तरह के एक समारोह में असंभव है कुछ के मामले में क्या है, तो यह एक अच्छा विचार हो सकता है डाल करने के लिए

यहाँ, या मैं नहीं बल्कि करना चाहिए (IMO भद्दा है, लेकिन यह बहस का मुद्दा है)

bigObject foo() { 
    bigObject result; 
    if(use_fixed_ret) 
     result = fixed_ret; 
    else{ 
     prepare_object(result); 
    } 
    return result; 
    } 
+0

मैं मानक का संदर्भ नहीं दे सकता, इसलिए मैं जवाब नहीं दूंगा, लेकिन मुझे यकीन है कि आपको std :: move की आवश्यकता नहीं है, मुझे लगता है कि आप आरवीओ को भ्रमित कर रहे हैं और प्रतिलिपि की प्रतिलिपि बना रहे हैं, प्रतिलिपि elision अनुकूलन है कि कुछ पर लाभ एक सिंगल रिटर्न पथ वाले कंपाइलर। बिगऑब्जेक्ट आर-वैल्यू का सम्मान बन जाएगा जहां यह लौटाया गया था। – 111111

+0

हां, मुझे लगता है कि कॉपी एलिजन शुरुआत में मेरा मतलब है। – leftaroundabout

+1

यदि आपको साफ कोड और कोड स्तर अनुकूलन पसंद हैं, तो आप ऐसा लगता है, :), आप अपने 'foo() 'फ़ंक्शन में' else {... 'शाखा से छुटकारा पा सकते हैं। जैसे कि पहला कथन सत्य है तो दूसरे का मूल्यांकन नहीं किया जाएगा। – 111111

उत्तर

33

स्थानीय चर के लिए, वहाँमें std::move करने के लिए उन्हें कोई आवश्यकता नहीं है 210 बयान समय † के अधिकांश, भाषा वास्तव में की मांग के बाद से है कि इस अपने आप होता है:

§12.8 [class.copy] p32

जब एक प्रतिलिपि आपरेशन के इलिजन के लिए मानदंडों को पूरा कर रहे हैं या तथ्य के लिए सेव पूरी की जाएगी कि स्रोत ऑब्जेक्ट एक फ़ंक्शन पैरामीटर है, और प्रतिलिपि बनाने वाली ऑब्जेक्ट को प्रतिलिपि के लिए कन्स्ट्रक्टर का चयन करने के लिए एक लवल्यू, ओवरलोड रिज़ॉल्यूशन द्वारा नामित किया गया है, जैसा कि ऑब्जेक्ट को रावल्यू द्वारा निर्दिष्ट किया गया था। यदि ओवरलोड रिज़ॉल्यूशन विफल रहता है, या यदि चयनित कन्स्ट्रक्टर के पहले पैरामीटर का प्रकार ऑब्जेक्ट के प्रकार (संभावित रूप से सीवी-क्वालिफाइड) के लिए एक रावल्यू संदर्भ नहीं है, तो ऑब्जेक्ट को एक लवल्यू के रूप में देखते हुए ओवरलोड रिज़ॉल्यूशन फिर से किया जाता है। [नोट: इस दो चरण के अधिभार रिज़ॉल्यूशन को निष्पादित किया जाना चाहिए चाहे कॉपी प्रतिलिपि हो। यह कथन को निर्धारित करने के लिए कन्स्ट्रक्टर को निर्धारित करता है, और कॉल का विस्तार होने पर भी चयनित कन्स्ट्रक्टर को सुलभ होना चाहिए। अंत टिप्पणी]


कॉपी इलिजन † बहुत जहां यह लागू किया जा सकता (§12.8/31) में प्रतिबंधित है। ऐसा एक प्रतिबंध यह है कि स्रोत ऑब्जेक्ट का प्रकार वापसी-कथन से निपटने के दौरान फ़ंक्शन के सीवी-अयोग्य रिटर्न प्रकार के समान होना चाहिए। यह स्थानीय चर के सबबजेक्ट्स के लिए भी लागू नहीं है जो दायरे से बाहर निकलने वाले हैं।

+2

और यहां आपके मानकों का संदर्भ है। – 111111

+1

ठीक है ... मुझे हमेशा मानक में फॉर्मूलेशन के साथ मेरी कठिनाइयों का सामना करना पड़ता है, इसे पांच बार पढ़ें और अभी भी यह समझ में नहीं आता कि इसका क्या अर्थ है। लेकिन आप कहते हैं, मेरे उदाहरण में, इसका मतलब यह है कि "पहला संस्करण जितना अच्छा हो उतना अच्छा है"? तब मैं तुम पर भरोसा रखूंगा। – leftaroundabout

+2

@ बाएंअराउंडबाउट: यह मूल रूप से कहता है "यदि ऑब्जेक्ट स्थानीय है, और मूल्य से वापस आ गया है, तो पहले इसे एक रैल्यू के रूप में वापस करने का प्रयास करें (जैसा कि 'std :: move' करेगा)। अगर उसे कोई चाल ctor नहीं मिलता है, कोशिश करें, लेकिन इस बार एक lvalue के रूप में। – Xeo

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