क्या std :: unordered_map ऑपरेटर [] गैर-एक्सिसिटिंग कुंजी के लिए शून्य-आरंभीकरण करता है?


25

Cppreference.com के अनुसार, std::map::operator[]गैर-मौजूदा मूल्य के लिए शून्य-आरंभीकरण है।

हालाँकि, एक ही साइट के लिए शून्य-आरंभीकरण का उल्लेख नहीं है std::unordered_map::operator[], सिवाय इसके कि एक उदाहरण है जो इस पर निर्भर करता है।

बेशक यह सिर्फ एक संदर्भ स्थल है, मानक नहीं। तो, ठीक है या नहीं नीचे कोड है?

#include <unordered_map>
int main() {
    std::unordered_map<int, int> map;
    return map[42];     // is this guaranteed to return 0?
}

13
@ Islex आप मज़बूती से परीक्षण नहीं कर सकते हैं अगर कुछ
आरम्भिक है

2
@ Havelex मुझे वास्तव में समझ नहीं आया, आप एक गैर-आरंभिक कैसे हो सकते हैं std::optional?
आईडीकेलेव ४६३०३५18१

2
@ Objectlex यह जांचने का कोई तरीका नहीं है कि क्या किसी ऑब्जेक्ट को इनिशियलाइज़ किया गया है या नहीं क्योंकि अनफिनिश्ड बिहेवियर में इनिशियलाइज़ेशन रिजल्ट्स के अलावा किसी अनइंस्टाल्यूटेड ऑब्जेक्ट पर कोई ऑपरेशन होता है। कोई std::optionalऑब्जेक्ट जो कोई सम्‍मिलित मान नहीं रखता है, वह अभी भी एक इनिशियलाइज्ड ऑब्जेक्ट है।
22

2
मान ऑब्जेक्ट वैल्यू-इनिशियलाइज़्ड है, न कि ज़ीरो-इनिशियलाइज़्ड। स्केलर प्रकारों के लिए ये समान हैं, लेकिन वर्ग प्रकारों के लिए वे भिन्न हैं।
aschepler

@ लोबोव मैंने कल ग्नू 17 और एसटीडी 17 का उपयोग करके इसका परीक्षण करने की कोशिश की, और विचित्र रूप से मुझे जो भी मिला वह शून्य प्रारंभिक था। मैंने सोचा कि std::optional has_valueयह परीक्षण करेगा लेकिन यह विफल रहता है, इसलिए मुझे लगता है कि आप सही हैं।
Æप्लेक्स

जवाबों:


13

हम जिस ओवरलोड के बारे में बात कर रहे हैं, उसके आधार पर [unord.map.elem] केstd::unordered_map::operator[] बराबर है

T& operator[](const key_type& k)
{
    return try_­emplace(k).first->second;
}

(एक अधिभार-संदर्भ लेने वाला अधिभार बस में चला जाता kहै try_emplaceऔर अन्यथा समान है)

यदि कोई तत्व kनक्शे में कुंजी के नीचे मौजूद है , तो try_emplaceउस तत्व के लिए एक पुनरावृत्ति देता है और false। अन्यथा, try_emplaceकुंजी के तहत एक नया तत्व सम्मिलित करता है k, और उस true [[unord.map.modifiers] के लिए एक पुनरावृत्ति देता है :

template <class... Args>
pair<iterator, bool> try_emplace(const key_type& k, Args&&... args);

हमारे लिए दिलचस्प यह है कि वहां कोई तत्व अभी तक मौजूद नहीं है [unord.map.modifiers] / 6 :

अन्यथा value_­typeनिर्मित प्रकार की वस्तु सम्मिलित करता हैpiecewise_­construct, forward_­as_­tuple(k), forward_­as_­tuple(std​::​forward<Args>(args)...)

(एक अधिभार-संदर्भ लेने वाला अधिभार बस में चला जाता kहै forward_­as_­tupleऔर, फिर से, अन्यथा समान है)

चूंकि value_typeएक pair<const Key, T> [unord.map.overview] / 2 है , यह हमें बताता है कि नए मानचित्र तत्व का निर्माण इस प्रकार किया जाएगा:

pair<const Key, T>(piecewise_­construct, forward_­as_­tuple(k), forward_­as_­tuple(std​::​forward<Args>(args)...));

चूंकि argsखाली आने के बाद से operator[], यह pairबिना किसी तर्कों के जोड़े के जोड़े के रूप में बनाए जा रहे हमारे नए मूल्य के लिए उबलता है [जोड़े.पेयर] / 14 जो प्रत्यक्ष आरंभीकरण है [class.base.init] / 7 प्रकार के मूल्य का Tउपयोग करना ()आरंभीकरण के रूप में जो मूल्य आरंभीकरण के लिए उबलता है [dcl.init] /17.4 । एक के मूल्य आरंभीकरण intशून्य आरंभीकरण है [dcl.init] / 8 । और intस्वाभाविक रूप से शून्य आरंभीकरण, int0 [dcl.init] / 6 को आरंभ करता है ।

तो हां, आपका कोड 0 लौटने की गारंटी है ...


21

आपके द्वारा लिंक की गई साइट पर यह कहते हैं:

जब डिफ़ॉल्ट एलोकेटर का उपयोग किया जाता है, तो यह कुंजी से कॉपी की जाने वाली कॉपी और मैप किए गए मूल्य को वैल्यू-इनिशियलाइज्ड किया जाता है।

तो intहै मूल्य प्रारंभ :

मूल्य आरंभीकरण के प्रभाव हैं:

[...]

4) अन्यथा, वस्तु शून्य-आरंभिक है

यही कारण है कि परिणाम है 0

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