सही उत्तर इस बात पर निर्भर करता है कि आप किस सी ++ मानक के बारे में बात कर रहे हैं।
यदि हम सी ++ 11 के बारे में बात कर रहे हैं, तो क्लैंग सही है (एक स्पष्ट कदम की आवश्यकता है)। अगर हम सी ++ 14 के बारे में बात कर रहे हैं, तो जीसीसी सही है (एक स्पष्ट कदम की आवश्यकता नहीं है)।
सी ++ 11 N3290/[class.copy]/p32 में कहते हैं:
When the criteria for elision of a copy operation are met or would be met save for the fact that the source object is a function parameter, and the object to be copied is designated by an lvalue, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. If overload resolution fails, ...
यह मांग करती है जब वापसी अभिव्यक्ति समारोह वापसी प्रकार के रूप में एक ही प्रकार है कि आप केवल निहित चाल मिलता है।
लेकिन CWG 1579 ने इसे बदल दिया, और यह दोष रिपोर्ट सी ++ 11 के बाद स्वीकार की गई, और सी ++ 14 के समय में। यह वही पैरा अब पढ़ता है:
When the criteria for elision of a copy/move operation are met, but not for an exception-declaration, and the object to be copied is designated by an lvalue, or when the expression in a return
statement is a (possibly parenthesized) id-expression that names an object with automatic storage duration declared in the body or parameter-declaration-clause of the innermost enclosing function or lambda-expression, overload resolution to select the constructor for the copy is first performed as if the object were designated by an rvalue. If the first overload resolution fails or was not performed, ...
इस संशोधन मूल रूप से वापसी अभिव्यक्ति प्रकार की अनुमति देता है परिवर्तनीय-टू समारोह वापसी प्रकार और अभी भी निहित चाल के लिए योग्य हो।
इसका मतलब यह है कि कोड की जरूरत है एक #if
/#else
__cplusplus
के मूल्य के आधार?
कोई ऐसा कर सकता है, लेकिन मुझे परेशान नहीं होगा।अगर मैं सी ++ 14 लक्षित कर रहे थे, मैं सिर्फ होगा: कोड अप्रत्याशित रूप से एक सी ++ 11 संकलक के तहत चलाया जाता है
return i;
हैं, तो आप त्रुटि के संकलन समय पर सूचित कर दिया जाएगा, और यह मामूली बात है ठीक करने के लिए:
return std::move(i);
तुम सिर्फ सी ++ 11 को लक्षित कर रहे हैं, तो move
का उपयोग करें।
तुम दोनों सी ++ 11 और सी ++ 14 (और आगे) को लक्षित करना चाहते हैं, तो move
का उपयोग करें। move
अनावश्यक रूप से उपयोग करने का नकारात्मक पक्ष यह है कि आप RVO (वापसी मूल्य अनुकूलन) को बाधित कर सकते हैं। हालांकि, इस मामले में, RVO भी नहीं कानूनी (समारोह की वापसी प्रकार के return
बयान से रूपांतरण की वजह से) है। और इसलिए अनावश्यक move
कुछ भी चोट नहीं करता है।
एक बार जब आप एक नि: शुल्क move
की ओर झुक सकता है यहां तक कि जब सी ++ 14 को लक्षित करता है, तो इसके बिना, चीज़ें अभी भी में सी ++ 11 संकलन, और एक महंगी प्रतिलिपि रूपांतरण आह्वान, के रूप में एक कदम का विरोध किया है रूपांतरण। इस मामले में, गलती से सी ++ 11 के तहत संकलन एक मूक प्रदर्शन बग पेश करेगा। और जब सी ++ 14 नि: शुल्क move
के तहत संकलित अभी भी कोई हानिकारक प्रभाव पड़ता है।
मुझे संदेह है कि हम बेहतर जवाब देने में सक्षम होंगे जब हम समझेंगे कि आपको इसके लिए क्या चाहिए। फिलहाल, इसे make_unique के बजाय make_shared को कॉल करके हल किया जा सकता है। मुझे लगता है कि ऐसा कुछ कारण है कि यह संभव नहीं है, और यह उस कारण को समझने में मदद करेगा। – Elliott
@Elliott: क्या हल किया जा सकता है? वह कुछ भी हल करने के लिए नहीं पूछ रहा है, वह पूछ रहा है कि उसके पास कोड सही है या नहीं। –