2015-11-20 9 views
5

मान लेते हैं कि मैं इस कदम constructor और operator=(Foo&&) साथ struct Foo करते हैं, और मैं डेटा सदस्य के रूप में यह प्रयोग किया है:सी ++ std :: चाल यहाँ खराब है?

Foo f() 
{ 
    Foo foo; 
    //code 
    return foo; 
} 
struct Boo { 
Foo foo; 
Boo() { 
    foo = f();//1 
    foo = std::move(f());//2 
} 
}; 

मामले (2) मैं वास्तव में std::move, लेकिन क्या अगर मैं इसे यहां इस्तेमाल की जरूरत नहीं , क्या यह कुछ खराब बनाता है, अनुकूलन को रोकने की तरह?

मैं इस पढ़ें: Why does std::move prevent RVO?

और RVO की return foo;return std::move(foo); के कारण अक्षम करने से बदल रहा है कि यह पता लगाना है, लेकिन क्या बारे में (2) यह इसी तरह की स्थिति पैदा कर रहा है? और यदि हां, तो क्यों?

+7

कॉपी इस मामले में लागू नहीं होगा क्योंकि आप 'foo.operator =' को कॉल कर रहे हैं। यदि आपके पास 'Foo foo = std :: move (f()) था, तो यह प्रासंगिक होगा;' प्रारंभिकरण है। –

+1

@ एमएम लेकिन 'क्लैंग 3.7' इस बारे में चेतावनी देते हैं, इसलिए मुझे आश्चर्य है, क्या यह चेतावनी पीढ़ी में बग है, या मुझे – user1244932

+1

कुछ याद आया यह कारणों से भी खराब हो सकता है जो प्रदर्शन कारण भी नहीं हैं। # 2 के लिए आपके मामले में, आप पहले से ही एक rhr पर std :: move (f()) को कॉल करने की परवाह करते हैं, इसलिए चाल बर्बाद हो जाती है। अंगूठे का मेरा नियम यह है कि आपको std :: move से बचना चाहिए जब तक कि आपको नहीं करना चाहिए, और आपको केवल तब ही करना होगा जब आप एक गैर-तुच्छ तरीके से स्वामित्व स्थानांतरित कर रहे हों। – IdeaHat

उत्तर

5

यह अनावश्यक और भ्रमित है। सिर्फ इसलिए कि के बजाय void*, या std::add_lvalue_reference_t<Foo> (या Foo bitand) के बजाय std::add_pointer_t<void> लिख सकता है, या इसका मतलब यह नहीं है कि मुझे चाहिए।

यह भी अन्य संदर्भों में मायने रखती है:

auto&& a = f(); // OK, reference binding to a temporary extends its lifetime 
auto&& b = std::move(f()); // dangling 

और हां, अगर Foo कुछ है कि अधिक दोहराया जा सकता है,

for(const auto& p : f()) {} // OK 
for(const auto& p : std::move(f())) {} // UB 

और अपने उदाहरण में, असाइनमेंट ऑपरेटर के रूप में कार्यान्वित किया जाता है, तो है कॉपी-एंड-स्वैप (operator=(Foo)), फिर foo = std::move(f()) एक गैर-भयानक चाल को मजबूर करता है, जबकि foo = f()f() के operator= के तर्क के लिए वापसी मूल्य को बढ़ा सकता है।

+0

उस पहले उदाहरण में, 'बी' 'VS2013' द्वारा संकलित किए जाने पर लटकता प्रतीत नहीं होता है। (अभी तक किसी अन्य कंपाइलर के साथ परीक्षण नहीं किया है)। क्या आप कृपया उस पर थोड़ी अधिक जानकारी प्रदान कर सकते हैं? –

+0

@DeanSeo न तो [clang] (http://coliru.stacked-crooked.com/a/607b0d720af30b9e) न ही [gcc] (http://coliru.stacked-crooked.com/a/698d5c5271c8f1c8) जीवन भर का विस्तार करेगा अस्थायी पूर्व कुछ अच्छी प्रदर्शन चेतावनियों को भी छोड़ देगा। –

+0

@ MatthäusBrandl मुझे नहीं लगता कि 'std :: move (f())' अभी तक अस्थायी है, लेकिन यह संभवतः एक xvalue के रूप में जल्द ही स्थानांतरित हो जाएगा। तो यह अभी तक नहीं ले जाया गया है ...? (जिसका अर्थ लटकना नहीं है)। मैंने इसे बहुत समय पहले पोस्ट किया था, इसलिए शायद मुझे पकड़ने के लिए कुछ समय चाहिए। –

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