2014-10-19 9 views
15

unordered_map :: emplace और unordered_map :: C++ में डालने के बीच क्या अंतर है?unordered_map :: emplace और unordered_map :: C++ में डालने के बीच क्या अंतर है?

+3

से एक [संदर्भ] ले ली (http://en.cppreference.com/w/cpp/container/unordered_map/emplace): क़ायम करना की * सावधान उपयोग करते समय अनावश्यक नकल से बचने के नए तत्व का निर्माण करने की अनुमति देता या संचालन ले जाएँ। नए तत्व के निर्माता (यानी 'std :: pair ') को उसी स्थान के साथ बुलाया जाता है, जैसा कि' std :: forward (args) के माध्यम से अग्रेषित किया गया है ... '। * – chris

+0

emplace एक नई वस्तु बनाता है जबकि सम्मिलित एक मौजूदा वस्तु लेता है।पैरामीटर अलग हैं क्योंकि इमस्थल कन्स्ट्रक्टर तर्क लेता है। यदि आपके पास सम्मिलित करने के लिए पहले से मौजूद कोई उदाहरण नहीं है, तो Emplace का उपयोग करें। –

उत्तर

25

unordered_map::insert प्रतियां या एक मूल्य-मूल्य जोड़ी को कंटेनर में ले जाती है। It is overloaded to accept reference-to-const or an rvalue reference:

std::pair<iterator,bool> insert(const std::pair<const Key, T>& value); 

template<class P> 
std::pair<iterator,bool> insert(P&& value); 

unordered_map::emplace आप जगह में तत्व का निर्माण करके अनावश्यक प्रतियां या चाल से बचने के लिए अनुमति देता है। यह forward arguments to the constructor of the key-value pair करने के लिए उपयुक्त अग्रेषण और एक variadic टेम्पलेट का उपयोग करता है:

template<class... Args> 
std::pair<iterator,bool> emplace(Args&&... args); 

लेकिन वहाँ दो कार्यों के बीच ओवरलैप के एक महान सौदा है। emplace कुंजी-मूल्य जोड़ी की प्रतिलिपि/चालक कन्स्ट्रक्टर को अग्रेषित करने के लिए उपयोग किया जा सकता है जो इसे insert के रूप में उपयोग करने की अनुमति देता है। इसका मतलब है कि emplace का उपयोग गारंटी नहीं देता है कि आप प्रतियां या चाल से बचेंगे। इसके अलावा insert का संस्करण जो एक रावल्यू-रेफरेंस लेता है वास्तव में टेम्पलेट होता है और P किसी भी प्रकार को स्वीकार करता है जैसे कुंजी-मान जोड़ी P से रचनात्मक है।

Scott Meyers says:

सिद्धांत रूप में, क़ायम कार्यों कभी कभी और अधिक कुशल उनकी प्रविष्टि समकक्षों की तुलना में होना चाहिए, और वे कभी भी कम कुशल होना चाहिए।

(संपादित करें: हावर्ड Hinnant भाग गया some experiments कि पता चला है कभी कभी insertemplace की तुलना में तेजी है)

आप निश्चित रूप से कॉपी/कंटेनर में ले जाने के लिए यह insert उपयोग करने के लिए है क्योंकि आप कर रहे हैं बुद्धिमान हो सकता है करना चाहते हैं यदि आप गलत तर्क देते हैं तो संकलन त्रुटि प्राप्त करने की अधिक संभावना है। आपको अधिक सावधान रहने की आवश्यकता है कि आप विस्थापन कार्यों के लिए सही तर्क पारित कर रहे हैं।

unordered_map::emplace के अधिकांश कार्यान्वयन नई जोड़ी के लिए गतिशील रूप से आवंटित किए जाएंगे, भले ही मानचित्र में पहले से ही उस कुंजी के साथ कोई आइटम हो और emplace विफल हो जाए। इसका मतलब यह है कि यदि कोई अच्छा मौका है कि emplace विफल हो जाए तो आप असफल गतिशील स्मृति आवंटन से बचने के लिए सम्मिलित करके बेहतर प्रदर्शन प्राप्त कर सकते हैं।

छोटे उदाहरण:

#include <unordered_map> 
#include <iostream> 

int main() { 
    auto employee1 = std::pair<int, std::string>{1, "John Smith"}; 

    auto employees = std::unordered_map<int, std::string>{}; 

    employees.insert(employee1); // copy insertion 
    employees.insert(std::make_pair(2, "Mary Jones")); // move insertion 
    employees.emplace(3, "James Brown"); // construct in-place 

    for (const auto& employee : employees) 
    std::cout << employee.first << ": " << employee.second << "\n"; 
} 

EDIT2: अनुरोध पर। unordered_map::emplace का उपयोग एक कुंजी या मान के साथ करना संभव है जो एक से अधिक कन्स्ट्रक्टर पैरामीटर लेता है। std::pairpiecewise constructor का उपयोग करके आप अभी भी अनावश्यक प्रतियों या चाल से बच सकते हैं।

#include <unordered_map> 
#include <iostream> 

struct Employee { 
    std::string firstname; 
    std::string lastname; 
    Employee(const std::string& firstname, const std::string& lastname) 
    : firstname(firstname), lastname(lastname){}  
}; 

int main() { 
    auto employees = std::unordered_map<int, Employee>{}; 
    auto employee1 = std::pair<int, Employee>{1, Employee{"John", "Smith"}}; 

    employees.insert(employee1); // copy insertion 
    employees.insert(std::make_pair(2, Employee{"Mary", "Jones"})); // move insertion 
    employees.emplace(3, Employee("Sam", "Thomas")); // emplace with pre-constructed Employee 
    employees.emplace(std::piecewise_construct, 
        std::forward_as_tuple(4), 
        std::forward_as_tuple("James", "Brown")); // construct in-place 
} 
+0

* "प्रतिस्थापन कार्य अक्सर उनके सम्मिलन समकक्षों की तुलना में अधिक कुशल होते हैं, और वे कभी भी कम कुशल नहीं होते हैं।" * हॉवर्ड हिन्नेंट ने कुछ अलग मापा: http://htmlpreview.github.io/?https://github.com/HowardHinnant /papers/blob/master/insert_vs_emplace.html यह भी देखें: https://groups.google.com/a/isocpp.org/forum/?fromgroups#!searchin/std-discussion/emplace/std-discussion/YQ4BGAvxIhw/jTfn1RIm9IkJ – dyp

+0

@dyp मोबाइल फ़ायरफ़ॉक्स पर मेरे लिए भी काम नहीं कर रहा है – Yakk

+0

@Yakk Ah, मुझे खेद है। उम्मीद है कि यह काम करता है: सहयोगी कंटेनरों के लिए https://groups.google.com/a/isocpp.org/d/topic/std-discussion/YQ4BGAvxIhw/discussion 'emplace' आम तौर पर तर्क से तत्व (केवल कुंजी नहीं) बनाता है भले ही इसे सम्मिलित न किया जाए। तो यदि आपके पास पहले से कोई तत्व है (सहयोगी कंटेनर के बाहर) और इसे कॉपी करना चाहते हैं, तो 'डालें' अधिक कुशल हो सकता है। – dyp

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