2013-02-06 20 views
15

आप मुझे सिखाने चाहेंगे क्यों दोनोंअधिभार :: सम्मिलित

std::unordered_map::insert(const value_type&) 

और

template<class P> std::unordered_map::insert(P&&) 

मानक में मौजूद हैं?

मुझे लगता है कि insert(P&&)insert(const value_type&) के रूप में कार्य कर सकता है।

+3

मौन ........ –

+0

संभवतः TR1 से विरासत। हो सकता है कि वे सुरक्षित रहें और कार्यों को न हटाएं, केवल उन्हें जोड़ें। शायद वे उस समय के प्रभाव पर निश्चित नहीं थे जो मौजूदा कोड पर हो सकता है जो TR1 का उपयोग करता था। –

+0

मैंने एक [प्रोग्राम] (http://liveworkspace.org/code/4y16As$46) बनाने की कोशिश की है जो संकलित करने में विफल रहता है यदि आप 'सम्मिलित करें (const value_type &)' को हटाते हैं, और असफल हो जाते हैं। किसी के पास विचार है? – Yakk

उत्तर

7
इन भार के

auto std::unordered_map::insert(const value_type&) -> ... 

template<class P> 
auto std::unordered_map::insert(P&&) -> ... 

की

दोनों के अपने फायदे हैं और न ही पूरी तरह से अन्य जगह ले सकता है।पहला लगता है जैसे P से दूसरे के विशेष मामले की तरह const value_type& हो सकता है। दूसरे अधिभार के बारे में अच्छी बात यह है कि आप अनावश्यक प्रतियों से बच सकते हैं। उदाहरण के लिए, इस मामले में:

mymap.insert(make_pair(7,"seven")); 

यहाँ, make_pair का परिणाम वास्तव में एक pair<int, const char*> जबकि value_typepair<const int, string> हो सकता है। तो, एक अस्थायी value_type ऑब्जेक्ट बनाने और को कंटेनर में कॉपी करने के बजाय, हमारे पास तर्क को परिवर्तित करके और/या अपने सदस्यों को स्थानांतरित करके सीधे value_type ऑब्जेक्ट को मानचित्र में बनाने का मौका है।

दूसरी ओर, यह अच्छा है कि अगर यह के रूप में अच्छी तरह से काम होगा:

mymap.insert({7,"seven"}); 

लेकिन इस सूची वास्तव में एक अभिव्यक्ति नहीं है! संकलक इसके कारण दूसरे अधिभार के लिए पी को कम नहीं कर सकता है। पहला अधिभार अभी भी व्यवहार्य है क्योंकि आप ऐसी सूची के साथ pair<const int,string> पैरामीटर को प्रतिलिपि बना सकते हैं।

+0

बहुत बहुत धन्यवाद !! चूंकि मैं पूरी तरह से समझ नहीं पा रहा हूं, फिर भी 'डालने (कॉन्स वैल्यू_ टाइप और) 'डालने के लिए व्यवहार्य क्यों है ({7," सात "}), मैंने मानक को और अधिक पढ़ा है। एक बार फिर धन्यवाद!! –

+0

मैंने एक [संबंधित प्रश्न] पोस्ट किया है (http://stackoverflow.com/questions/14757809/overload-of-stdunordered-mapinsert-reloaded)। –

2

अंतर संदर्भ के प्रकार में निहित है। पहले

std::unordered_map::insert(const value_type&) 

एक संदर्भ (सी ++ 03) अब में (सी ++ 11) एक lvalue संदर्भ कहा जाता है का उपयोग करता है। यह स्थिर होना चाहिए। सी ++ 11 पेश किए गए रावल संदर्भ P&& जो कि स्थिर नहीं होना चाहिए। दोनों के लिए अनुमति देने के लिए, दो सम्मिलित कार्य प्रदान किए जाते हैं।

कृपया C++ 11 में स्टैक ओवरव्लो wrt rvalue संदर्भों पर यह उत्कृष्ट उत्तर देखें, मुझे उम्मीद है कि यह आपके प्रश्न का उत्तर देने में मदद करेगा।

What does T&& (double ampersand) mean in C++11?

जैसा कि आपने कहा, यह rvalue-अधिभार उपयोग करने के लिए और सिर्फ एक स्थिरांक lvalue रेफरी गुजरती हैं, लेकिन संभव है - http://msdn.microsoft.com/en-us/library/dd293668.aspx

By overloading a function to take a const lvalue reference or an rvalue reference, you can write code that distinguishes between non-modifiable objects (lvalues) and modifiable temporary values (rvalues).

-Hannes से इस पाठ को देखने

+0

ओह, लिंक की पुनरावृत्ति के लिए खेद है। जब मैंने अभी तक कोई जवाब नहीं दिया, तो मैंने अपना जवाब लिखना शुरू कर दिया, लेकिन बाधित हो गया। –

+1

दोनों लिंक किए गए पदों के पहले भाग (लगभग चलने वाले अर्थशास्त्र के बारे में) पढ़ने के बजाय, आपको संभवतः पूर्ण अग्रेषण और संदर्भ ढहने वाले नियमों के संबंध में दूसरे भाग भी पढ़ना चाहिए। चूंकि 'डालने' या तो उत्तीर्ण तर्क को प्रतिलिपि या स्थानांतरित करेगा, इसलिए इसमें कोई भी कारण नहीं है, जिसमें मूल्यवर्ग और रालुओं के बीच खुद को सम्मिलित करने का कोई कारण नहीं है, 'value_type' का कन्स्ट्रक्टर आपके लिए ऐसा करेगा। –

4

टेम्पलेट सार्वभौमिक संदर्भ अधिभार n1858 में तर्क के साथ जोड़ा गया था (map के लिए, लेकिन यह स्पष्ट रूप से multimap पर लागू होता है):

Two of the insert signatures are new. They have been added to allow moving from rvalue types other than value_type , which are convertible to value_type . When P instantiates as an lvalue, the argument is copied into the map , else it is moved into the map (const qualifiers permitting).

(अन्य insert हस्ताक्षर सम्मिलित-साथ-संकेत है करने के लिए भेजा।)

हम भी deque के लिए तर्क का उल्लेख (फिर से, स्पष्ट रूप से अन्य कंटेनरों के लिए संदर्भित):

All member functions which insert (or append, prepend, etc.) a single value_type into the container are overloaded with a member function that accepts that value_type by rvalue reference so that single value_type's can be moved into the container. This not only makes working with heavy weight types much more efficient, it also allows one to insert movable but non-copyable types into the container.

यह स्पष्ट है कि परिवर्तन मुख्य रूप से जोड़ों के रूप में माना जाता था; उस समय पर विचार नहीं किया गया था कि टेम्पलेट अधिभार मूल (सी ++ 03) insert पूरी तरह से बदल सकता है। यह पहले के n1771, जो टेम्पलेट अधिभार के लिए कुछ प्रेरणा प्रदान करता है की चर्चा करते हुए, एक अलग दृष्टिकोण लेने के द्वारा देखा जा सकता है: (। CCCopyConstructible के लिए एक संक्षिप्त नाम है)

Note below that for map and multimap that there are two new insert overloads, both taking a pair with a non-const key_type. One can not move from a const key_type, and therefore to be able to move a key_type into the (multi)map, a pair must be used. There are overloads for both a const lvalue pair, and a non-const rvalue pair so that lvalue pair's will not be moved from.

pair<iterator, bool> insert(const value_type& x); // CC 
pair<iterator, bool> insert(const pair<key_type,mapped_type>& x); // CC 
pair<iterator, bool> insert(pair<key_type,mapped_type>&& x); 

यह तो दिखाई देने वाले template ओवरलोड को map और multimap में जोड़ा गया था, यह महसूस किए बिना कि उन्होंने const value_type & ओवरलोड को अनावश्यक बनाया है। आप अनावश्यक अधिभार को हटाने के लिए एक दोष रिपोर्ट सबमिट करने पर विचार कर सकते हैं।

+0

उत्तर के लिए धन्यवाद। हालांकि, मुझे लगता है कि फॉर्म 'डालने ({...}) '(sellibitze के उत्तर में) भी उपयोगी है, भले ही एक प्रतिलिपि होती है। –

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