2011-01-07 7 views
23
typedef map<KeyType, ValType> KVMap; 
KVMap kvmap; 

kvmap.insert(KVMap::value_type(key, val)); 
kvmap.insert(make_pair(key, val)); 

ऊपर दिए गए विकल्पों में से कौन सा एक एसटीएल नक्शा करने के लिए सम्मिलित करने के लिए हमेशा तेज है? क्यूं कर?सी ++: value_type बनाम make_pair, जो मानचित्र डालने के लिए तेज़ है?

नोट: मुझे अच्छी तरह पता है कि insert() मानचित्र पर कुंजी-मूल्य जोड़े जोड़ने (अपडेट नहीं) जोड़ने के लिए []= का उपयोग करने से तेज़ है। कृपया मान लें कि मेरी क्वेरी जोड़ने के बारे में है, अद्यतन नहीं है। इसलिए मैंने इसे insert() तक सीमित कर दिया है।

+5

जब तक आपके प्रोग्राम में नक्शे पर आवेषण शामिल नहीं होते हैं, तो क्या आपको सच में लगता है कि कोई गति अंतर ध्यान देने योग्य होगा? धीमे धब्बे वास्तव में क्या हैं यह देखने के लिए आपको अपने तैयार, स्वच्छ, रखरखाव योग्य कार्यक्रम को प्रोफ़ाइल करने के लिए प्रोफ़ाइल प्राप्त करनी चाहिए। और इनलाइनिंग के बाद, कोई अंतर नहीं होना चाहिए। – GManNickG

+0

जीएमएन: अंतर छोटा था। कार्ल के जवाब पर मेरी टिप्पणी देखें। –

उत्तर

19

संभावना हैं कि पहले हो जाएगा 'एप्सिलॉन-तेजी से', इस वजह से (23.3.1 से मानक में):

typedef pair<const Key, T> value_type; 

[...] 

pair<iterator, bool> insert(const value_type& x); 
  • पहले संस्करण में, आप सीधे निर्माण उचित द्वारा std::map<K,V>::insert

  • की उम्मीद दूसरे संस्करण में प्रकार, std::pair टेम्पलेट निर्माता का उपयोग करके रूपांतरण शामिल है। दरअसल, std::make_pair सबसे अधिक संभावना अपने टेम्पलेट तर्क KeyType और ValType करने के लिए, अनुमान होगा इस प्रकार एक std::pair<KeyType, ValType> लौटने।

    यह पैरामीटर प्रकार std::map<K,V>::insert से मेल नहीं खाता है, जो std::pair<const KeyType, ValType> है (अंतर const-पहले वैध है)। std::pair रूपांतरण कन्स्ट्रक्टर का उपयोग std::pair<K, V> से std::pair<const K, V> बनाने के लिए किया जाएगा।

निष्पक्ष रहते हुए मेरा मानना ​​है कि नहीं तुम भी अंतर को मापने सकता है (और मैं भी यकीन है कि लोकप्रिय compilers वास्तव में इन के लिए एक अलग कोड उत्पन्न होगा नहीं कर रहा हूँ)।

+0

और इनलाइनिंग के बाद? – GManNickG

+0

@GMan: ईमानदारी से? कोई विचार नहीं :( – icecrime

+0

यह * प्रति से * में रेखांकित नहीं है जो ओवरहेड को खत्म कर देगा, बल्कि प्रतिलिपि निर्माण/असाइनमेंट इत्यादि के बाद के elision –

2

वे मूल रूप से वही बात हैं। KVMap::value_typestd::pair<KeyType, ValType> के लिए टाइप किया गया है, इसलिए यह केवल कन्स्ट्रक्टर को कॉल कर रहा है। std::make_pair एक टेम्पलेट फ़ंक्शन है जो केवल कन्स्ट्रक्टर को कॉल करता है (यह अस्तित्व में है क्योंकि टेम्पलेट प्रकारों को मुफ्त कार्यों के लिए घटाया जा सकता है, लेकिन कन्स्ट्रक्टर के लिए नहीं)। एक बार सभी अविश्वसनीय-मानक अनुकूलन किए जाने के बाद, कोई अंतर होने का कोई कारण नहीं है।

मैं आप कैसे परीक्षण कर रहे हैं पता नहीं है, लेकिन वहाँ है कि गलत करने के लिए कई, कई तरीके हैं।

बनाम operator[] के माध्यम से बनाम बनाम, बाद वाले को अवधारणात्मक रूप से अधिक काम करना पड़ता है (जब आप इस तरह एक नया तत्व जोड़ते हैं, तो पहले इसे एक तत्व को डिफॉल्ट-निर्माण करना होता है, और उसके बाद इसे ऊपर निर्दिष्ट किया जाता है) , लेकिन ValType के आधार पर, यह अनुमानतः मूल रूप से एक ही चीज़ में अनुकूलित किया जा सकता है।

+0

मुझे विश्वास है कि आप थोड़ा गलत हैं: मेरा उत्तर देखें – icecrime

+0

@icecrime मुझे लगता है कि आपके पास एक बिंदु है। जब यह कॉन्स्टेस को कम करने की बात आती है तो सी ++ तरह का भद्दा इमो है। :) –

+0

वे वही मानते कुंजी हैं, मान सही प्रकार हैं। यह आमतौर पर एक समस्या नहीं होने वाला है लेकिन कभी-कभी ऑटो रूपांतरण अप्रत्याशित हो सकता है इसलिए मैं value_type (कुंजी, वैल) का उपयोग करना पसंद करता हूं। उदाहरण: कुंजी = "std :: string"। make_pair ("Plop", 1) प्रारंभ में एक value_type ऑब्जेक्ट नहीं बनाता है हालांकि यह अंततः परिवर्तित हो जाएगा और अनुकूलन एक अच्छा संकलक पर सभी रूपांतरणों को हटा सकता है। –

11

वास्तव में value_typemake_pair से अधिक होने का तर्क है। ऐसा इसलिए है क्योंकि, विभिन्न आर्केन कारणों के लिए, make_pair मूल्य के आधार पर अपने तर्क स्वीकार करता है। दूसरी ओर, value_type, std::pair<const Key, value> के लिए उपनाम, इसके कन्स्ट्रक्टर को कॉन्स्ट संदर्भ द्वारा पारित तर्कों के साथ बुलाया जाएगा। make_pair में पास-बाय-रेफरेंस के विरुद्ध पास-बाय-वैल्यू से दक्षता का संभावित नुकसान होता है, जो सिद्धांत में आपके कार्यक्रम पर एक उल्लेखनीय प्रभाव डाल सकता है।

एक और मुद्दा के बारे में make_pair साथ कि make_pair आमतौर पर बनाम std::pair<const Key, Value>map अंदर की जरूरत प्रकार std::pair<Key, Value> की एक जोड़ी बनाएगा है चिंतित होना चाहिए। इसका मतलब यह है कि रूपांतरण सही तरीके से काम करने के लिए pair के इस समय एक और अनावश्यक प्रतिलिपि बनाई जा सकती है।

संक्षेप में,, make_pair का उपयोग कर के कारण हो सकता कुंजी और मान के दो पूरी तरह से अनावश्यक प्रतियां बना पाने के लिए value_type निर्माता का उपयोग करते समय कोई भी नहीं है।

4

यह सिर्फ एक पूरक है।

insert(make_pair(...)) अन्य उत्तरदाताओं के कारण के कारण 4 बार नोट कन्स्ट्रक्टर की प्रतिलिपि बनाते हैं।

insert(value_type(...)) कॉल कन्स्ट्रक्टर 2 बार कॉल करता है।

operator[] एक बार डिफ़ॉल्ट कन्स्ट्रक्टर को कॉल करता है और एक ठेठ कार्यान्वयन में कन्स्ट्रक्टर 2 गुना कॉपी करता है। डिफ़ॉल्ट कन्स्ट्रक्टर operator[] के अंदर insert(value_type(..., mapped_type())) के लिए बुलाया जाता है। कॉपी कन्स्ट्रक्टर को insert() के तर्क (pair), की प्रतिलिपि बनाने के लिए और मानचित्र के आंतरिक नोड को प्रतिलिपि बनाने के लिए एक बार बुलाया जाता है।

तो, अगर आप का उपयोग insertmake_pair साथ, यह कहा नहीं जा सकता है कि insert हमेशा तेजी से operator[] से भी जोड़ने के लिए है। शायद, यह स्थिति पर निर्भर करता है। जैसा कि आप जानते हैं, उपरोक्त को देखते हुए, emplace को नए मानक के लिए प्रस्तावित किया गया था।

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