स्टिक कुछ ट्रेसिंग की चर 'एक्स' नकल खाली सेट का आह्वान करते हैं और इस के लिए मुख्य बदलें:
int main(int argc, char *argv[]) {
printf("map\n");
std::map<int, vec> z;
printf("vec\n");
vec x;
printf("pair\n");
std::pair<int,vec> y(1,x);
printf("insert\n");
z.insert(y);
printf("inserted 1\n");
y.first = 2;
printf("insert\n");
z.insert(y);
printf("inserted 2\n");
}
आउटपुट:
$ make mapinsert CXXFLAGS=-O3 -B && ./mapinsert
g++ -O3 mapinsert.cpp -o mapinsert
map
vec
pair
getMem n 0 ptr 0x6b0258
insert
getMem n 0 ptr 0x6b0268
getMem n 32 ptr 0x6b0278
getMem n 0 ptr 0x6b02a0
FreeMemory ptr 0x6b0268
inserted 1
insert
getMem n 0 ptr 0x6b0268
getMem n 32 ptr 0x6b02b0
getMem n 0 ptr 0x6b02d8
FreeMemory ptr 0x6b0268
inserted 2
FreeMemory ptr 0x6b0258
FreeMemory ptr 0x6b02d8
FreeMemory ptr 0x6b02b0
FreeMemory ptr 0x6b02a0
FreeMemory ptr 0x6b0278
अपने 3 0 आकार allo की तो cations:
- एक खाली वेक्टर को जोड़ी में कॉपी करना है।
- एक मानचित्र में खाली वेक्टर की एक प्रति स्टोर करना है।
ये दोनों स्पष्ट रूप से आवश्यक हैं। क्या मैं के बारे में यकीन नहीं है यह है:
- एक
insert
करने के लिए कॉल में कहीं वेक्टर कॉपी करने के लिए है, और यह भी कॉल को सम्मिलित करने में कर सकती है।
यह ऐसा है insert
(या कुछ और यह कॉल आंतरिक रूप से) ने अपने पैरामीटर मान के बजाय संदर्भ द्वारा ले जा रहा है, या insert
स्पष्ट रूप से कुछ समय के एक स्वत: चर में एक प्रति ले जा रहा है इससे पहले कि यह नया नक्शा नोड आवंटित करता है। इस समय एक डीबगर फायरिंग मेरे लिए प्रयास है, मैं इसे किसी और को छोड़ दूंगा।
संपादित करें: रहस्य हल हो गया। insert
std::pair<const int, vec>
लेता है, std::pair<int, vec>
नहीं। एक खाली वेक्टर की अतिरिक्त प्रतिलिपि इसलिए है क्योंकि आपके द्वारा बनाई गई जोड़ी को एक (नोटर) अस्थायी रूप में परिवर्तित किया जाना चाहिए, फिर उस अस्थायी का संदर्भ insert
पर भेजा गया है। std :: pair में एक कंस्ट्रक्टर टेम्पलेट है जो आपको लगभग किसी भी चीज़ से दूर जाने देता है। 20.2.2/4:
template<class U, class V> pair(const pair<U,V> &p);
प्रभाव: तर्क के इसी सदस्यों में से सदस्यों initializes, की जरूरत के रूप में प्रदर्शन अंतर्निहित रूपांतरण।
मैं भी देख सकते हैं कि मेरी कार्यान्वयन में, vec x;
getMem
फोन नहीं है, लेकिन vec x(0);
करता है। तो वास्तव में:
z[1] = vec();
कम कोड है और आप अतिरिक्त प्रतिलिपि बनाने के लिए अवसर से इनकार करते हैं (हालांकि यह operator=
कॉल के बजाय)। यह अभी भी मेरे लिए कम से कम 2 0 आकार के आवंटन करता है।
सी ++ मानक परिभाषित करता है ताकि insert
पर एक कॉल शामिल एक निर्दिष्ट अभिव्यक्ति के परिणाम को वापस कर सके। मुझे यकीन नहीं है कि इसका मतलब है कि operator[]
के प्रभाव "जैसे" make_pair
और insert
कहलाए गए थे (यानी, मानक यह निर्धारित करने के लिए उतना ही अच्छा है जितना स्रोत operator[]
के लिए होना चाहिए), या केवल मान दिया गया मान है निर्दिष्ट अभिव्यक्ति के समान मूल्य उत्पन्न होगा। यदि उत्तरार्द्ध तो शायद एक कार्यान्वयन इसे एक 0-आकार के आवंटन के साथ कर सकता है। लेकिन निश्चित रूप से map
में पहली बार एक जोड़ी बनाने के बिना प्रविष्टि बनाने की कोई गारंटी नहीं है जिसमें मैप किए गए प्रकार हैं, इसलिए 2 आवंटन की अपेक्षा की जानी चाहिए। या अधिक ठीक से, वांछित मैप किए गए मूल्य की 2 प्रतियां: तथ्य यह है कि 0-आकार वाले वेक्टर की प्रतिलिपि बनाने से 0-आकार का आवंटन कार्यान्वयन-निर्भर होता है।
इसलिए, यदि आप एक मामले में जहां मूल्य वास्तव में कॉपी करने के लिए महंगा है, लेकिन वास्तव में डिफ़ॉल्ट-निर्माण (तत्वों के बहुत सारे के साथ एक कंटेनर की तरह) के लिए सस्ती थी, उसके बाद निम्न उपयोगी हो सकता है:
std::map<int, vec> z;
vec x(1000);
z[1] = x;
// i.e. (*(z.insert(std::pair<const int, vec>(1,vec())).first)).second = x;
, आकार 4000 और आकार 0 में से 2 का 2 आवंटन में आता है, जबकि:
std::map<int, vec> z;
vec x(1000);
z.insert(std::pair<const int, vec>(2, x));
आकार 4000 के 3 बनाता है और आकार 0. में से कोई भी अंततः आकार काफी बड़ा है कि पहले कोड में अतिरिक्त आवंटन की तुलना में सस्ता है दूसरे कोड में अतिरिक्त प्रतिलिपि।
यह संभव है कि सी ++ 0x में चालक रचनाकार इससे मदद करेंगे, मुझे यकीन नहीं है।
आपके सभी प्रयासों के लिए धन्यवाद। अगर मैं यह जवाब दे सकता हूं *, मैं चाहता हूं। –
यह एक अच्छा उदाहरण है कि नक्शा में वैक्टर जैसे चीजों को डालने का सबसे अच्छा अभ्यास क्यों टाइप किया गया है टाइपिफ़ वेक्टर vec_t; टाइपपीफ मानचित्र map_t; vec_t डमी; map_t myvals; vec_t tvals (100000,3);/* vallue */myvals.insert (map_t :: value_type (1, डमी))। पहला-> second.swap (tvals); इसका नक्शा नोड बनाने के लिए केवल खाली vec_t की प्रतिलिपि बनाने का प्रभाव होता है, और उसके बाद नोड का निर्माण होने के बाद मानों को इसमें स्थानांतरित किया जाता है (या यदि यह पहले से मौजूद है तो प्रतिस्थापित किया गया है)। समकक्ष सी ++ 0x रास्ता myvals.insert है (map_t :: value_type (1, std :: move (tvals))); –