Std :: unordered_map operatörü [] mevcut olmayan anahtar için sıfır başlatma yapıyor mu?


25

Cppreference.com'a göre, varolmayan std::map::operator[]değer sıfır başlatma yapar.

Bununla birlikte, aynı site buna sıfır sıfırlamadan bahsetmez std::unordered_map::operator[], ancak buna dayanan bir örnek yoktur.

Tabii ki bu sadece bir referans sitesi, standart değil. Peki, aşağıdaki kod tamam mı değil mi?

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

13
@ Lex bir şeyin başlatıldığını güvenilir bir şekilde test
edemezsiniz

2
@ Ælex Gerçekten anlamıyorum, nasıl başlatılmamış olabilirsiniz std::optional?
idclev 463035818

2
@ Ælex, bir nesnenin başlatılıp başlatılmadığını test etmenin bir yolu yoktur, çünkü başlatılmadan başka başlatılmamış bir nesne üzerindeki herhangi bir işlem Tanımsız Davranış ile sonuçlanır. std::optionalİçerilen değeri olmayan bir nesne hala başlatılmış bir nesnedir.
bolov

2
Değer nesnesi, sıfırla başlatılmaz, değerle başlatılır. Skaler tipler için bunlar aynıdır, ancak sınıf tipleri için farklıdırlar.
aschepler

@bolov Dün gnu 17 ve std 17 kullanarak test etmeye çalıştım ve tuhaf bir şekilde elimde olan tek şey sıfır başlatma oldu. std::optional has_valueTest edeceğini düşündüm ama başarısız oldu, bu yüzden sanırım haklısın.
Declex

Yanıtlar:


13

Hangi aşırı yükten bahsettiğimize bağlı olarak, [unord.map.elem]std::unordered_map::operator[] ile eşdeğerdir.

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

(bir rvalue referansı alan aşırı yük sadece kiçine girer try_emplaceve aynıdır)

kHaritadaki anahtarın altında bir öğe varsa , o try_emplaceöğeye bir yineleyici ve döndürür false. Aksi takdirde, try_emplaceanahtarın altına yeni bir öğe ekler kve buna bir yineleyici ve true [unord.map.modifiers] döndürür :

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

Bizim için ilginç olan, henüz bir unsur olmamasıdır [unord.map.modifiers] / 6 :

Aksi takdirde value_­type,piecewise_­construct, forward_­as_­tuple(k), forward_­as_­tuple(std​::​forward<Args>(args)...)

(bir rvalue referansı alan aşırı yük sadece kiçine girer forward_­as_­tupleve yine aynıdır)

Yana value_typebir olduğunu pair<const Key, T> [unord.map.overview] / 2 , bu yeni harita elemanı olarak inşa edilecektir söyler:

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

Yana argsgelen zaman boş olan operator[]bu yeni değeri bir üyesi olarak inşa edilen kaynar aşağı pairbir argümanlar [pairs.pair] / 14 doğrudan başlatma olan [class.base.init] / 7 tipte bir değer Tkullanılarak ()değer başlangıcına kadar kaybolan başlatıcı olarak [dcl.init] /17.4 . A değerinin başlatılması intsıfır başlatma [dcl.init] / 8'dir . Ve intdoğal olarak sıfır başlatma intbunu 0 [dcl.init] / 6 olarak başlatır .

Evet, kodunuzun 0 döndüreceği garantilidir…


21

Bağlantı verdiğiniz sitede şöyle diyor:

Varsayılan ayırıcı kullanıldığında, anahtarın anahtardan kopyalanmasına ve eşlenen değerin değerin başlatılmasına neden olur.

Yani intbir değer başlatıldı :

Değer başlatmanın etkileri şunlardır:

[...]

4) Aksi takdirde, nesne sıfır başlatılır

Sonuç bu yüzden 0.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.