पहले से निर्मित वस्तुओं के लिए C ++ 11 push_back () std के साथ कदम: emplace_back () की क्षमता


86

C ++ 11 emplace_back()में आम तौर पर पसंद किया जाता है (दक्षता के संदर्भ में) push_back()क्योंकि यह इन-प्लेस निर्माण की अनुमति देता है, लेकिन क्या यह अभी भी मामला है जब push_back(std::move())पहले से निर्मित वस्तु के साथ उपयोग किया जाता है?

उदाहरण के लिए, emplace_back()अभी भी निम्नलिखित मामलों में पसंद किया जाता है?

std::string mystring("hello world");
std::vector<std::string> myvector;

myvector.emplace_back(mystring);
myvector.push_back(std::move(mystring));
// (of course assuming we don't care about using the value of mystring after)

इसके अतिरिक्त, क्या इसके बजाय उपरोक्त उदाहरण में कोई लाभ है:

myvector.emplace_back(std::move(mystring));

या यहाँ कदम पूरी तरह से बेमानी है, या कोई प्रभाव नहीं है?


myvector.emplace_back(mystring);प्रतियां और कदम नहीं है। अन्य दो चालें और समतुल्य होनी चाहिए।
टीसी

जवाबों:


116

आइए देखें कि आपके द्वारा प्रदान किए गए विभिन्न कॉल क्या हैं:

  1. emplace_back(mystring): यह नए तत्व का इन-प्लेस निर्माण है जिसमें आपने जो भी तर्क दिया है। चूंकि आपने एक अंतराल प्रदान किया था, इसलिए वास्तव में इन-प्लेस निर्माण एक प्रतिलिपि-निर्माण है, अर्थात यह कॉलिंग के समान हैpush_back(mystring)

  2. push_back(std::move(mystring)): यह चाल-सम्मिलन को कॉल करता है, जो std :: string ist in-place चाल-निर्माण के मामले में होता है।

  3. emplace_back(std::move(mystring)): यह आपके द्वारा प्रदान किए गए तर्कों के साथ फिर से एक जगह का निर्माण है। चूंकि यह तर्क एक प्रतिद्वंद्विता है, इसलिए यह चाल-निर्माणकर्ता को कॉल करता है std::string, अर्थात यह 2 की तरह एक जगह पर चलने वाला निर्माण है।

दूसरे शब्दों में, यदि टाइप टी के एक तर्क के साथ कहा जाता है, तो यह एक प्रतिद्वंद्विता या अंतराल है, emplace_backऔर push_backसमकक्ष हैं।

हालांकि, किसी भी अन्य तर्क (रों) के लिए, emplace_back, रेस जीत एक साथ उदाहरण के लिए char const*एक में vector<string>:

  1. emplace_back("foo")string::string(char const*)इन-प्लेस-निर्माण के लिए कॉल करता है ।

  2. push_back("foo")पहले string::string(char const*)फ़ंक्शन के हस्ताक्षर से मेल खाने के लिए आवश्यक अंतर्निहित रूपांतरण के लिए कॉल करना होगा, और फिर केस 2. जैसे एक चाल-सम्मिलन। इसलिए यह बराबर हैpush_back(string("foo"))


1
मूव कंस्ट्रक्टर आमतौर पर कॉपी कंस्ट्रक्टर्स की तुलना में अधिक कुशल होता है, इसलिए समान शब्दार्थ के बावजूद रलवे (केस 2, 3) का उपयोग करना अधिक प्रभावी होता है।
रयान ली

ऐसी स्थिति के बारे में क्या? शून्य foo (string && s) {वेक्टर .emplace (s); // 1 वेक्टर.emplace (std :: Move (s)); // 2}
वीएलओडी

@VALOD फिर से मेरी सूची के नंबर 1 और 3 हैं। sरेवल्यू संदर्भ के रूप में परिभाषित किया जा सकता है जो केवल प्रतिद्वंद्वियों को बांधता है, लेकिन अंदर foo, sएक अंतराल है।
अर्ने मर्ट्ज़

1

Emplace_back को प्रतिद्वंद्वियों के संदर्भों की एक सूची मिलती है और जगह में सीधे एक कंटेनर तत्व का निर्माण करने की कोशिश करता है। आप सभी प्रकार के साथ emplace_back को कॉल कर सकते हैं जो कंटेनर तत्व कंस्ट्रक्टर्स का समर्थन करता है। जब मापदंडों के लिए emplace_back कॉल करें जो संदर्भ संदर्भ नहीं हैं, तो यह सामान्य संदर्भों में 'वापस गिर जाता है' और जब पैरामीटर और कंटेनर तत्व समान प्रकार के होते हैं तो कम से कम कॉपी कंस्ट्रक्टर को नहीं बुलाया जाता है। आपके मामले में 'myvector.emplace_back (मिस्ट्रिंग)' को स्ट्रिंग की एक प्रति बनाना चाहिए क्योंकि कंपाइलर को पता नहीं चल सका कि पैरामीटर myvector चल रहा है। तो एसटीडी डालें: जो आपको वांछित लाभ देता है उसे स्थानांतरित करें। पुश_बैक को पहले से निर्मित तत्वों के लिए और साथ ही emplace_back पर काम करना चाहिए।


2
यह अग्रेषण / सार्वभौमिक संदर्भों का वर्णन करने का एक दिलचस्प तरीका है।
टीसी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.