2013-02-13 18 views
17
auto&& mytup = std::make_tuple(9,1,"hello"); 
    std::get<0>(mytup) = 42; 
    cout << std::get<0>(mytup) << endl; 
  1. वहाँ एक कॉपी/(RVO के बिना) शामिल ले जाने के लिए जब make_tuple से लौट रहे है?
  2. क्या यह अपरिभाषित व्यवहार पैदा कर रहा है?
  3. मैं दोनों सार्वभौमिक संदर्भ लिख सकते हैं। auto&& var = func()auto var = func() के बजाय हमेशा इस्तेमाल किया जा सकता है ताकि कोई प्रतिलिपि/चाल न हो?
+0

एक संदर्भ एक संदर्भ है। –

+0

'ऑटो और& var = func()', http://stackoverflow.com/questions/13618506/is-it-possible-to-stdmove-objects-out-of-functions-c11/13618587#13618587 – billz

+3

@billz के संबंध में लिंक एक अलग मामला है जहां यह संदर्भ के रूप में स्थानीय चर लौटा रहा है। बग फ़ंक्शन के अंदर है जहां इसे कहा जाता है। – balki

उत्तर

7
  1. हां। किसी फ़ंक्शन से कोई भी रिटर्न जो किसी संदर्भ प्रकार को वापस नहीं करता है, में प्रतिलिपि/चाल शामिल हो सकती है। एलवीओ यही है कि आरवीओ क्या है। जिस वस्तु का आपका संदर्भ बाध्य है, उसे किसी भी तरह से प्रारंभ करने की आवश्यकता है।

  2. नहीं। ऐसा क्यों होना चाहिए? संदर्भ के लिए बाध्य अस्थायी/प्रचलित जीवनकाल संदर्भ के दायरे से निर्धारित होता है।

  3. समारोह() एक संदर्भ प्रकार वापस नहीं करता है, वहाँ

    auto&& var = func(); 
    

    और

    auto var = func(); 
    
    के बीच दक्षता में कोई अंतर (और न ही व्यवहार)

नहीं होना चाहिए, तो

दोनों मामलों में जीवन भर के साथ एक वस्तु युक्त ब्लॉक के अंत में एक वस्तु का निर्माण किया जाता है। एक मामले में इसका अपना नाम होता है, दूसरे में इसे संदर्भ के माध्यम से नामित किया जाता है। दोनों मामलों में नाम का उपयोग एक लाभा के रूप में किया जा सकता है। आरवीओ किसी भी मामले में समान रूप से अच्छी तरह से लागू किया जा सकता है।

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

यदि func() एक संदर्भ वापस कर सकता है, तो चीजें बहुत अलग हैं - उस स्थिति में आपको यह तय करना होगा कि आप प्रतिलिपि बनाना/स्थानांतरित करना चाहते हैं या नहीं।

+0

यदि मजेदार 'Foo & func()', 'auto &&'' जैसे lvalue को वापस करने के लिए हुआ, तो 'auto' – balki

+0

@balki की प्रतिलिपि बनायेगा, लेकिन हम यहां एक मूल्य-वापसी समारोह पर चर्चा कर रहे थे। अब मैं भेद स्पष्ट कर दिया। – JoergB

+0

"संदर्भ के लिए बाध्य अस्थायी/प्रचलितता का जीवनकाल संदर्भ के दायरे से निर्धारित होता है।" सी ++ 11 में यह नया है? सी + 03 में यह केवल एक कॉन्स्ट संदर्भ के लिए सच था। – Suma

0

make_tuple करने के लिए कॉल के मूल्यांकन का परिणाम एक tuple इन्स्टेन्शियशन के prvalue अस्थायी है। autoप्रकार-विनिर्देशक को उसी tuple तत्काल (7.1.6.4p6) के रूप में अनुमानित किया जाएगा, इसलिए mytuptuple<...> && प्रकार का है। अस्थायी अस्थायी जीवनकाल-संदर्भ mytup (12.2p5) द्वारा विस्तारित किया जाता है।

  1. क्योंकि अस्थायी समारोह द्वारा दिया गया मान है, वहाँ कोई कॉपी/शामिल लाएं (make_tuple भीतर RVO अभी भी हो सकता है) है।
  2. व्यवहार पूरी तरह से परिभाषित किया गया है।
  3. लगभग सभी मामलों के लिए, mytup को एक लालसा के रूप में माना जाएगा, भले ही इसका प्रकार एक रावल्यू संदर्भ है। हालांकि auto && का उपयोग करने का कोई मतलब नहीं है क्योंकि सभी समझदार कंपाइलर्स अस्थायी से कॉपी/चाल को बढ़ाएंगे।

स्पष्ट करने के लिए, एक ही रास्ता mytup इलाज किया है के रूप में एक rvalue std::forward<decltype(mytup)>(mytup) उपयोग करने के लिए, What does auto&& tell us? में के रूप में है के बारे में; हालांकि यदि आप mytup (tuple<...> इस मामले में) के प्रकार जानते हैं तो आप std::move का भी उपयोग कर सकते हैं।

14

यह उस मामले में केवल समस्याग्रस्त है जहां प्रारंभकर्ता एक फ़ंक्शन कॉल है जो एक अल्पकालिक रावल्यू संदर्भ देता है। कम शब्दों और अधिक कोड के साथ:

// Fine; lifetime extension applies! 
auto&& ref = 42; 

auto id = [](int&& i) -> int&& { return std::move(i); }; 
auto&& uhoh = id(42); 
// uhoh is now a stale reference; can't touch it! 

इसके विपरीत, auto uhoh = id(42); ठीक काम किया होता।

आपके मामले में, क्योंकि std::make_tuple एक मूल्य देता है और एक रैल्यू संदर्भ नहीं है कोई समस्या नहीं है।

मेरा मानना ​​है कि असली खतरा उन कार्यों और फ़ंक्शन टेम्पलेट्स से है जो रावल्यू संदर्भ पैरामीटर के साथ हैं और जो कुछ उप-प्रोजेक्ट्स के लिए एक रावल्यू संदर्भ देता है जो जीवनकाल उन पर निर्भर करता है। (ऐसा कहा जा रहा है, auto&& ref = std::move(42); जितना सरल है समस्या को प्रदर्शित करता है!)

स्थिति सी ++ 11 से पूरी तरह से नई नहीं है, इस पर विचार करें: T const& ref = bar(T_factory());

+4

+1, मुझे याद है कि टी टी कॉन्स्ट एंड पास (टी कॉन्स एंड टी) {रिटर्न टी; } 'उदाहरण जब अस्थायी संदर्भों के संदर्भों के संदर्भ में क्लैंग की पहचान में सुधार करने की कोशिश की जा रही है ... यह दुर्भाग्यपूर्ण है कि इसे * संभावित * मुद्दों का पता लगाने के लिए अंतर-प्रक्रियात्मक विश्लेषण की आवश्यकता है: x –

0

सी ++ (सी ++ 11 से पहले भी) में एक विशिष्ट नियम है जो कहता है कि अगर आप अस्थायी के अस्थायी के संदर्भ को बाध्य करते हैं तो संदर्भ के जीवनकाल तक बढ़ाया जाएगा।

एक सरल मामला है:

int foo() { 
    return 42; 
} 

int bar() { 
    const int& x = foo(); 
    return x; // Here is safe to use x 
} 
+2

नियम केवल कॉन्स्ट संदर्भ के लिए है। मुझे नहीं लगता कि यह स्पष्ट ऑटो है && एक संदर्भ संदर्भ है - है ना? – Suma

+0

@ सुमा: एक संदर्भ कंपाइलर बैक-एंड के लिए एक संदर्भ है। कॉन्स्ट-इफेक्शन केवल फ्रंट-एंड को प्रभावित करता है (कानूनी क्या है और क्या नहीं है) और अनिर्धारित व्यवहार या प्रदर्शन के बारे में कोई भूमिका निभाता है। – 6502

+0

ऐसा लगता है कि मैं गलत हूं। मैं मानक में कॉन्स के बारे में कुछ भी नहीं देख सकता, इसी वाक्य में कहा गया है कि "जब कोई संदर्भ अस्थायी रूप से बाध्य होता है" 12.2 में, कम से कम सी ++ 11 ड्राफ्ट में। ट्यूटोरियल कॉन्स के बारे में बात करते हैं, लेकिन शायद यह एक सादा है और वैसे भी अस्थायी नहीं हो सकता है। – Suma