Yineleyici geçersiz kılma kuralları


543

C ++ kapsayıcıları için yineleyici geçersiz kılma kuralları nelerdir?

Tercihen özet liste formatında.

(Not: Bu, Stack Overflow'ın C ++ SSS'si için bir giriş anlamına gelir . Bu formda bir SSS sağlama fikrini eleştirmek istiyorsanız, tüm bunları başlatan metadaki yayınlama bunu yapmak için yer olacaktır. bu soru SSS fikrinin ilk başta başladığı C ++ sohbet odasında izlenir , bu nedenle cevabınızın bu fikri ortaya çıkaranlar tarafından okunması muhtemeldir.)


Cevaplar cevabınızla aynı formatta olmalı mı?
PW

@PW IMO, simetri için tercih edilirdi ama zorlayamam: P
Orbit'te Hafiflik Yarışları

c ++ 20 ne olacak?
Walter

1
@Walter Henüz mevcut değil;)
Orbit'te Hafiflik Yarışları

Bu soru, Futurama'dan Leela'yı aptal çağlardan alıntılamak ve mütevazı görüşüme göre açık bırakılmalıdır.
Roman Luštrik

Yanıtlar:


111

C ++ 17 (Tüm referanslar CPP17'nin son çalışma taslağından alınmıştır - n4659'un alınmıştır )


sokma

Sekans Kapları

  • vector: Fonksiyonlar insert, emplace_back, emplace, push_backneden yeniden tahsis yeni boyut eski kapasitesinden daha büyükse. Yeniden konumlandırma, dizideki öğelere atıfta bulunan tüm referansları, işaretçileri ve yineleyicileri geçersiz kılar. Yeniden tahsis olmazsa, ekleme noktasından önceki tüm yineleyiciler ve referanslar geçerliliğini korur. [26.3.11.5/1] Fonksiyon
    ile ilgili olarak reserve, yeniden tahsis dizideki elemanlara atıfta bulunan tüm referansları, işaretçileri ve tekrarlayıcıları geçersiz kılar. Bir çağrının ardından reserve(), bir eklemenin vektörün boyutunu değerinden büyük hale getireceği zamana kadar gerçekleşen eklemeler sırasında hiçbir yeniden tahsis yapılmayacaktır capacity(). [26.3.11.3/6]

  • deque: Deque'nin ortasındaki bir ekleme, tüm yineleyicileri ve deque unsurlarına referansları geçersiz kılar. Deque'nin her iki ucundaki bir ekleme, deque için tüm yineleyicileri geçersiz kılar, ancak deque öğelerine yapılan referansların geçerliliği üzerinde hiçbir etkisi yoktur. [26.3.8.4/1]

  • list: Yineleyicilerin ve referansların geçerliliğini etkilemez. Bir istisna atılırsa herhangi bir etkisi olmaz. [26.3.10.4/1]. , , , , , Fonksiyonlar bu kuralın kapsamındadır.
    insertemplace_frontemplace_backemplacepush_frontpush_back

  • forward_list: Aşırı yüklemelerin hiçbiri, insert_afteryineleyicilerin ve referansların geçerliliğini etkilemez [26.3.9.5/1]

  • array: Kural olarak , bir dizi yineleyicileri dizinin ömrü boyunca geçersiz kılınmaz. Bununla birlikte, takas sırasında, yineleyicinin aynı dizi öğesine işaret etmeye devam edeceğini ve böylece değerini değiştireceğini unutmayın.

İlişkili Kaplar

  • All Associative Containers: insertVe emplaceüyeleri yineleyicilerin geçerliliğini ve konteynere yapılan referansları etkilemeyecektir [26.2.6 / 9]

Sırasız İlişkili Konteynerler

  • All Unordered Associative Containers: Yeniden şekillendirme yineleyicileri geçersiz kılar, öğeler arasındaki sıralamayı değiştirir ve öğelerin hangi kovalarda göründüğünü değiştirir, ancak işaretçileri veya öğelere referansları geçersiz kılmaz. [26.2.7 / 9] ve konteynerin hususları da geçerliliğini etkilemez, ancak kabın tüm yineleyicileri geçersiz kılabilir. [26.2.7 / 14] ve eğer üye Yineleyicilerin geçerliliğini etkilemez burada, ekleme işlemi için önceden kapta elemanlarının sayısını, eklenen elemanların sayısı olup, özelliği , kabın kova sayısıdır, ve
    insertemplace
    insertemplace(N+n) <= z * BNnBz bir kabın maksimum yük faktörü. [/ 15 26.2.7]

  • All Unordered Associative Containers: Bir birleştirme işlemi (örn. a.merge(a2)) Durumunda , aktarılan öğelere atıf yapan yineleyiciler ve atıfta bulunan tüm yineleyiciler ageçersiz olur, ancak kalan öğelere yineleyiciler a2geçerli kalacaktır. (Tablo 91 - Sırasız ilişkilendirilebilir konteyner gereksinimleri)

Konteyner Adaptörleri

  • stack: temel kaptan miras alınan
  • queue: temel kaptan miras alınan
  • priority_queue: temel kaptan miras alınan

silme

Sekans Kapları

  • vector: Silme noktasında veya sonrasındaki işlevler eraseve pop_backgeçersizleştiriciler ve referanslar. [26.3.11.5/3]

  • deque: Silme işleminin son öğesini silen bir silme işlemi, dequeyalnızca son-uç yineleyiciyi ve tüm yineleyicileri ve silinen öğelere yapılan başvuruları geçersiz kılar. Bir dequeson öğenin değil , ilk öğesinin ilk öğesini silen bir silme işlemi yalnızca yineleyicileri ve silinen öğelere yapılan başvuruları geçersiz kılar. Ne ilk öğeyi ne de son öğeyi silen bir silme işlemi, son dequeuç yineleyiciyi ve tüm yineleyicileri geçersiz kılar ve öğenin tüm öğelerine başvurur deque. [Not: pop_frontve pop_backsilme işlemleridir. —Son notu] [26.3.8.4/4]

  • list: Yalnızca yineleyicileri ve silinen öğelere yapılan başvuruları geçersiz kılar. [26.3.10.4/3]. Bu uygulandığı erase, pop_front, pop_back, clearfonksiyonlar.
    removeve remove_ifüye işlevleri: iAşağıdaki koşulların geçerli olduğu bir liste yineleyicisi tarafından belirtilen listedeki tüm öğeleri siler : *i == value, pred(*i) != false. Yalnızca yineleyicileri ve silinen öğelere yapılan referansları geçersiz kılar [26.3.10.5/15].
    uniqueüye işlevi - iAralıktaki yineleyici tarafından atıfta bulunulan her ardışık eşit öğe grubundan ilk öğe dışındaki tüm öğeleri siler (yüklemin bağımsız değişkeni olan benzersiz sürümü için). Yalnızca yineleyicileri ve silinen öğelere yapılan başvuruları geçersiz kılar. [26.3.10.5/19][first + 1, last) olan *i == *(i-1)(bağımsız değişkenler ile eşsiz versiyonu için) ya dapred(*i, *(i - 1))

  • forward_list: erase_afteryalnızca yineleyicileri ve silinen öğelere yapılan referansları geçersiz kılar. [26.3.9.5/1].
    removeve remove_ifüye işlevleri - Aşağıdaki koşulların geçerli olduğu bir liste yineleyicisi tarafından belirtilen listedeki tüm öğeleri siler: *i == value(for remove()), pred(*i)true (for remove_if()). Yalnızca yineleyicileri ve silinen öğelere yapılan referansları geçersiz kılar. [26.3.9.6/12].
    uniqueüye işlevi - Yineleyici i tarafından [ilk + 1, son) aralığındaki *i == *(i-1)(bağımsız değişkeni olmayan sürüm için) veya pred(*i, *(i - 1))(yüklemli sürüm için ) her ardışık eşit öğe grubundan ilk öğe dışındaki tüm öğeleri siler argüman) tutar. Yalnızca yineleyicileri ve silinen öğelere yapılan referansları geçersiz kılar. [26.3.9.6/16]

  • All Sequence Containers: cleara öğelerine atıfta bulunan tüm referansları, işaretçileri ve yineleyicileri geçersiz kılar ve son kullanıcı yineleyicisini geçersiz kılabilir (Tablo 87 - Sekans kabı gereksinimleri). Ancak forward_list, clearsonuncu yineleyicileri geçersiz kılmaz. [26.3.9.5/32]

  • All Sequence Containers: assign kabın elemanlarına ilişkin tüm referansları, işaretçileri ve yinelemeleri geçersiz kılar. İçin vectorve dequeaynı zamanda geçmiş uç yineleyici geçersiz kılmaktadır. (Tablo 87 - Sekans kabı gereksinimleri)

İlişkili Kaplar

  • All Associative Containers: erase Üyeler yalnızca yineleyicileri ve silinen öğelere yapılan referansları geçersiz kılacaktır [26.2.6 / 9]

  • All Associative Containers: extract Üyeler, kaldırılan öğeye yalnızca yineleyicileri geçersiz kılar; kaldırılan öğeye işaretçiler ve referanslar geçerliliğini korur [26.2.6 / 10]

Konteyner Adaptörleri

  • stack: temel kaptan miras alınan
  • queue: temel kaptan miras alınan
  • priority_queue: temel kaptan miras alınan

Yineleyici geçersiz kılma ile ilgili genel kapsayıcı gereksinimleri:

  • Aksi belirtilmedikçe (açıkça veya diğer işlevler açısından bir işlev tanımlayarak), bir kapsayıcı üye işlevini çağırmak veya bir kapsayıcıyı bir kitaplık işlevine argüman olarak iletmek, o kapsayıcı içindeki nesnelere yineleyicileri geçersiz kılmamalı veya değerlerini değiştirmemelidir . [/ 12 26.2.1]

  • hiçbir swap()işlev, değiştirilen kapların elemanlarına atıfta bulunan referansları, göstergeleri veya yinelemeleri geçersiz kılmaz. [Not: end () yineleyicisi herhangi bir öğeye gönderme yapmadığından geçersiz kılınabilir. —Son notu] [26.2.1 / (11.6)]

Yukarıdaki gereksinimlere örnek olarak:

  • transformalgoritma: opve binary_opişlevleri yineleyicileri veya alt aralıkları geçersiz kılmamalı veya aralıklardaki öğeleri değiştirmemelidir [28.6.4 / 1]

  • accumulatealgoritma: [ilk, son] aralığında, binary_opöğeleri değiştiremez , yineleyicileri veya alt aralıkları geçersiz kılmaz [29.8.2 / 1]

  • reducealgoritma: binary_op yineleyicileri veya alt aralıkları geçersiz kılmaz ya da [ilk, son] aralığındaki öğeleri değiştirmez. [29.8.3 / 5]

ve bunun gibi...


7
Oh PW you hero!
Orbit'te Hafiflik Yarışları

2
@LightnessRacesinOrbit: Orijinal yanıt biçiminize göre yapmaya çalıştım. :)
PW

1
ayrıca bir girişimiz olabilir std::stringmi? Bence bu std::vectorSSO nedeniyle farklı
sp2danny

1
@ sp2danny: TOA nedeniyle, stringyukarıda listelenen ikinci genel gereksinim başarısız olur. Ben de dahil etmedim. Ayrıca önceki SSS girişlerinin aynı desenine sadık kalmaya çalıştı.
PW

@LightnessRaceswithMonica Sıkı çalıştığınız için teşekkürler. Günlerce kafamı karıştıran bir sorum var. "Geçersiz" bu bağlamlarda tam olarak ne anlama geliyor? "invalidated" can mean "no longer points to what it used to", not just "may not point to any valid element"Bu cevapta açıklanan @Marshall Clow demek ? Yoksa sadece 2 koşuldan sadece birini mi gösterir?
Rick

410

C ++ 03 (Kaynak: Yineleyici Geçersiz Kılma Kuralları (C ++ 03) )


sokma

Sekans kapları

  • vector: yeni kap boyutu önceki kapasiteden büyük olmadığı sürece ekleme noktasından önceki tüm yineleyiciler ve referanslar etkilenmez (bu durumda tüm yineleyiciler ve referanslar geçersiz kılınır) [23.2.4.3/1]
  • deque: eklenen üye deque'nin bir ucunda (ön veya arka) olmadığı sürece tüm yineleyiciler ve referanslar geçersiz kılınır (bu durumda tüm yineleyiciler geçersiz kılınır, ancak öğelere referanslar etkilenmez) [23.2.1.3/1]
  • list: etkilenmeyen tüm yineleyiciler ve referanslar [23.2.2.3/1]

İlişkili konteynerler

  • [multi]{set,map}: etkilenmeyen tüm yineleyiciler ve referanslar [23.1.2 / 8]

Konteyner adaptörleri

  • stack: temel kaptan miras alınan
  • queue: temel kaptan miras alınan
  • priority_queue: temel kaptan miras alınan

silme

Sekans kapları

  • vector: silme noktasından sonraki her yineleyici ve referans geçersiz kılınır [23.2.4.3/3]
  • deque: silinen üyeler deque'nin sonunda (ön veya arka) olmadığı sürece tüm yineleyiciler ve referanslar geçersiz kılınır (bu durumda yalnızca yineleyiciler ve silinen üyelere yapılan referanslar geçersiz kılınır) [23.2.1.3/4]
  • list: yalnızca yineleyiciler ve silinen öğeye yapılan başvurular geçersiz kılınır [23.2.2.3/3]

İlişkili konteynerler

  • [multi]{set,map}: yalnızca yineleyiciler ve silinen öğelere yapılan başvurular geçersiz kılınır [23.1.2 / 8]

Konteyner adaptörleri

  • stack: temel kaptan miras alınan
  • queue: temel kaptan miras alınan
  • priority_queue: temel kaptan miras alınan

yeniden boyutlandırma

  • vector: ekleme / silme başına [23.2.4.2/6]
  • deque: ekleme / silme başına [23.2.1.2/1]
  • list: ekleme / silme başına [23.2.2.2/1]

Not 1

Aksi belirtilmedikçe (açıkça veya diğer işlevler açısından bir işlev tanımlayarak), bir kapsayıcı üye işlevini çağırmak veya bir kapsayıcıyı bir kitaplık işlevine argüman olarak iletmek , o kapsayıcı içindeki nesnelere yineleyicileri geçersiz kılmamalı veya değerlerini değiştirmemelidir . [23.1 / 11]

Not 2

C ++ 2003'te "son" yineleyicilerin yukarıdaki kurallara tabi olup olmadığı açık değildir ; Her neyse, öyle olduklarını varsaymalısınız (pratikte olduğu gibi).

Not 3

İşaretçilerin geçersiz kılınması için kurallar, referansların geçersiz kılınması için kurallar olarak kullanılan adlardır.


5
İyi fikir, sadece sözler için: Ben düşünüyorum ilişkisel konteynerler tek bir satır içinde birlikte katlanabilir olabilir ve buna değer daha sonra başka bir çizgi ekleyerek olabilir sırasız ilişkisel ben gerçi ... olanlardan emin rehashing parçası olabilir nasıl ekleme / silme konusunda eşleştirilirse, bir rehash'ın tetiklenip tetiklenmeyeceğini kontrol etmenin bir yolunu biliyor musunuz?
Matthieu M.Haz

1
IIRC, spec bir yerde son yineleyici "o kap içindeki nesnelere" yineleyici olmadığını söylüyor. Bu garantilerin her durumda son yineleyiciyi nasıl aradığını merak ediyorum?
Johannes Schaub - litb

1
@MuhammadAnnaqeeb: Bu cevap, bir kısayol aldığım için bunu açıkça ifade etmiyor, ancak amaç yeniden boyutlandırma , bir yeniden tahsis gerekiyorsa olduğu gibi , ekleme / silme olduğunu söylemektir. ardından etkilenen tüm öğeleri yeniden yerleştirin. Cevabın bu bölümü kesinlikle geliştirilebilir.
Yörüngedeki Hafiflik Yarışları

1
@Yakk: Ama öyle değil; atıfta bulunulan standart metne bakın. Görünüşe göre C ++ 11'de düzeltildi. :)
Yörüngedeki Hafiflik Yarışları

1
@metamorphosis: deque, verileri bitişik olmayan bloklarda saklar. Başlangıç ​​ya da bitiş eklemek yeni bir blok tahsis edebilir, ancak asla önceki öğelerin etrafında hareket etmez, bu nedenle işaretçiler geçerli kalır. Ancak yeni bir blok tahsis edilirse bir sonraki / önceki öğeye gitme kuralları değişir, bu nedenle yineleyiciler geçersiz kılınır.
Nick Matteo

357

C ++ 11 (Kaynak: Yineleyici Geçersiz Kılma Kuralları (C ++ 0x) )


sokma

Sekans kapları

  • vector: yeni kap boyutu önceki kapasiteden büyük olmadığı sürece, ekleme noktasından önceki tüm yineleyiciler ve referanslar etkilenmez (bu durumda tüm yineleyiciler ve referanslar geçersiz kılınır) [23.3.6.5/1]
  • deque: eklenen üye deque'nin bir ucunda (ön veya arka) olmadığı sürece tüm yineleyiciler ve referanslar geçersiz kılınır (bu durumda tüm yineleyiciler geçersiz kılınır, ancak öğelere referanslar etkilenmez) [23.3.3.4/1]
  • list: etkilenmeyen tüm yineleyiciler ve referanslar [23.3.5.4/1]
  • forward_list: etkilenmeyen tüm yineleyiciler ve referanslar (için geçerlidir insert_after) [23.3.4.5/1]
  • array: (yok)

İlişkili konteynerler

  • [multi]{set,map}: etkilenmeyen tüm yineleyiciler ve referanslar [23.2.4 / 9]

Sıralanmamış ilişkilendirilebilir kaplar

  • unordered_[multi]{set,map}: tekrarlama meydana geldiğinde tüm yineleyiciler geçersiz kılınır, ancak referanslar etkilenmez [23.2.5 / 8]. Ekleme, kabın boyutunun maksimum yük faktörünün ve mevcut kova sayısının z * Bbulunduğu zyeri aşmasına neden olmazsa yeniden şekillendirme gerçekleşmez B. [/ 14 23.2.5]

Konteyner adaptörleri

  • stack: temel kaptan miras alınan
  • queue: temel kaptan miras alınan
  • priority_queue: temel kaptan miras alınan

silme

Sekans kapları

  • vector: silme noktasındaki veya sonrasındaki her yineleyici ve referans geçersiz kılınır [23.3.6.5/3]
  • deque: son öğenin silinmesi yalnızca yineleyicileri geçersiz kılar ve silinen öğelere ve geçmiş son yineleyiciye yapılan başvuruları geçersiz kılar; ilk elemanın silinmesi sadece yineleyicileri ve silinen elemanlara referansları geçersiz kılar; diğer öğelerin silinmesi tüm yineleyicileri ve referansları geçersiz kılar (son yineleyici dahil) [23.3.3.4/4]
  • list: yalnızca yineleyiciler ve silinen öğeye yapılan başvurular geçersiz kılınır [23.3.5.4/3]
  • forward_list: yalnızca silinenler ve yinelenen öğeye yapılan başvurular geçersiz kılınır (geçerlidir erase_after) [23.3.4.5/1]
  • array: (yok)

İlişkili konteynerler

  • [multi]{set,map}: yalnızca yineleyiciler ve silinen öğelere yapılan başvurular geçersiz kılınır [23.2.4 / 9]

Sırasız ilişkilendirilebilir kaplar

  • unordered_[multi]{set,map}: yalnızca yineleyiciler ve silinen öğelere yapılan başvurular geçersiz kılınır [23.2.5 / 13]

Konteyner adaptörleri

  • stack: temel kaptan miras alınan
  • queue: temel kaptan miras alınan
  • priority_queue: temel kaptan miras alınan

yeniden boyutlandırma

  • vector: insert / delete başına [23.3.6.5/12]
  • deque: ekleme / silme başına [23.3.3.3/3]
  • list: ekleme / silme başına [23.3.5.3/1]
  • forward_list: insert / delete başına [23.3.4.5/25]
  • array: (yok)

Not 1

Aksi belirtilmedikçe (açıkça veya diğer işlevler açısından bir işlev tanımlayarak), bir kapsayıcı üye işlevini çağırmak veya bir kapsayıcıyı bir kitaplık işlevine argüman olarak iletmek , o kapsayıcı içindeki nesnelere yineleyicileri geçersiz kılmamalı veya değerlerini değiştirmemelidir . [/ 11 23.2.1]

Not 2

swap () işlevi, değiştirilmekte olan kapların öğelerine başvuran tüm başvuruları, işaretçileri veya yinelemeleri geçersiz kılar . [Not: end () yineleyicisi herhangi bir öğeye gönderme yapmadığından geçersiz kılınabilir . —Son notu] [23.2.1 / 10]

Not 3

Yukarıdaki uyarı ile ilgili olarak dışında swap(), bu "son" yinelemeler yukarıda listelenen başına kabın kurallarına bağlı olup olmadığı açık değildir ; her neyse, öyle olduğunu varsaymalısınız.

Not 4

vectorve en azından konteynerin boyutu büyüyene kadar hiçbir otomatik yeniden boyutlandırmanın gerçekleşmeyeceğini garanti eden tüm sırasız ilişkisel konteyner desteği . Sırasız ilişkili bir kapsayıcılarla dikkat edilmelidir, çünkü gelecekteki bir teklif, yeterli işlemden sonra yeniden doldurmanın gerçekleşmesine izin verecek bir minimum yük faktörünün belirlenmesine izin verecektir ; garanti, bir potansiyel satıştan sonra geçersiz sayılmalıdır .reserve(n)ninserteraseerase


Ayrıca swap(), kopyalama / taşıma atamasında yineleyici geçerliliği için kurallar nelerdir?
goodbyeera

@LightnessRacesinOrbit: Ekleme, silme, yeniden boyutlandırma ve takas gibi, kopyalama / taşıma ataması da std :: vector'un üye işlevleridir, bu yüzden onlar için yineleyici geçerlilik kurallarını da sağlayabileceğinizi düşünüyorum.
goodbyeera

@goodbyeera: Öğe atamak kopyala / taşı demek mi? Bu, yineleyicileri etkilemez. Neden olsun ki? Sen vuruyorlar Not 1 üzerindedir.
Orbit'te Hafiflik Yarışları

1
Sanırım bir hata yaptım, çünkü std::basic_stringbir kapsayıcı olarak sayılmıyor gibi görünüyor ve kesinlikle notun geçerli olduğu bölümünde bir kap değil. Yine de, TOA'ya izin verilmediğini nereden söylüyor (COW olduğunu biliyorum)?
Tekilleştirici

2
Bu kurallar C ++ 14'te aynı mıdır? C ++ 17 (bilindiği kadarıyla)?
einpoklum

40

Bu ekleyerek muhtemelen değer olduğunu her hangi bir türdeki insert yineleyici ( std::back_insert_iterator, std::front_insert_iterator,std::insert_iterator bütün eklemeler bu yineleyici yoluyla gerçekleştirilir ve başka hiçbir bağımsız yineleyici-geçersiz olay meydana geldiğinde) sürece geçerli kalmasını garanti edilir.

Örneğin, bir içine yerleştirme işlemleri serisi gerçekleştirirken std::vectorkullanarakstd::insert_iterator bunu bu eklemeleri bu vektör içine tüm yineleyicinızı o "nokta" geçersiz edecek olan vektör yeniden tahsisini tetikleyecektir oldukça mümkündür. Bununla birlikte, söz konusu insert yineleyicinin geçerli kalması garanti edilir, yani yerleştirme sırasına güvenli bir şekilde devam edebilirsiniz. Vektör yeniden tahsisini tetikleme konusunda endişelenmenize gerek yok.

Bu, yine, sadece insert yineleyicinin kendisi üzerinden gerçekleştirilen insertler için geçerlidir. Yineleyici geçersiz kılma olayı kap üzerindeki bazı bağımsız eylemlerle tetiklenirse, ekleme yineleyicisi de genel kurallara uygun olarak geçersiz kılınır.

Örneğin, bu kod

std::vector<int> v(10);
std::vector<int>::iterator it = v.begin() + 5;
std::insert_iterator<std::vector<int> > it_ins(v, it);

for (unsigned n = 20; n > 0; --n)
  *it_ins++ = rand();

vektör bu işlemin ortasında bir yerlere yeniden tahsis etmeye karar verse bile, vektör içine geçerli bir ekleme dizisi gerçekleştirmesi garanti edilir. Yineleyici itaçıkça geçersiz it_insolacak , ancak geçerli olmaya devam edecektir.


22

Bu soru çok fazla oy topladığı ve bir SSS haline geldiği için, C ++ 03 ve C ++ 11 arasında, std::vectorekleme işleminin etkisi üzerindeki önemli bir farktan bahsetmek için ayrı bir cevap yazmak daha iyi olurdu . göre yineleyiciler ve referansları geçerliliği reserve()ve capacity()en upvoted cevap bildirime başarısız.

C ++ 03:

Yeniden konumlandırma, dizideki öğelere atıfta bulunan tüm referansları, işaretçileri ve yineleyicileri geçersiz kılar. Rezerv () çağrısından sonra, bir eklemenin vektörün boyutunu en son rezerv () çağrısında belirtilen boyuttan daha büyük hale getireceği zamana kadar gerçekleşen eklemeler sırasında yeniden tahsis edilmemesi garanti edilir .

C ++ 11:

Yeniden konumlandırma, dizideki öğelere atıfta bulunan tüm referansları, işaretçileri ve yineleyicileri geçersiz kılar. Rezerv () çağrısından sonra, bir eklemenin vektörün boyutunu kapasite () değerinden daha büyük hale getireceği zamana kadar gerçekleşen eklemeler sırasında yeniden tahsis edilmemesi garanti edilir .

Yani C ++ 03'te, unless the new container size is greater than the previous capacity (in which case all iterators and references are invalidated)diğer cevapta belirtildiği gibi " " değil , bunun yerine " greater than the size specified in the most recent call to reserve()" olmalıdır . Bu, C ++ 03'ün C ++ 11'den farklı olduğu bir şeydir. C ++ 03'te, bir kez bir insert()vektör boyutunun önceki reserve()çağrıda belirtilen değere ulaşmasına neden olur (bu, akım istenenden daha küçük olabilir, capacity()çünkü istenilenden daha büyük bir reserve()sonuca neden olabilir capacity()), sonraki herhangi biri insert()yeniden tahsise neden olabilir ve geçersiz kılınabilir tüm yineleyiciler ve referanslar. C ++ 11'de bu olmayacak ve her zaman capacity(), bir sonraki yeniden tahsisin boyut aşılmadan gerçekleşmeyeceğini kesin olarak bilmeye güvenebilirsiniz capacity().

Sonuç olarak, bir C ++ 03 vektörü ile çalışıyorsanız ve ekleme işlemi yaparken bir yeniden tahsinin gerçekleşmeyeceğinden emin olmak istiyorsanız, daha önce geçtiğiniz argümanın reserve()boyutunu değil, çağrının dönüş değeri capacity(), aksi takdirde kendinizi " erken " yeniden tahsis sürpriz olabilir .


14
Ancak, bunu bana yapan herhangi bir derleyiciyi vuracaktım ve topraktaki hiçbir jüri beni mahkum etmeyecekti.
Yakk - Adam Nevraumont

9
Bunu "fark edemedim"; C ++ 11'de düzeltilen bir C ++ 03 yazım hatasıydı. Hiçbir ana derleyici hatadan yararlanamaz.
Yörüngedeki Hafiflik Yarışları

1
@Yakk Bence gcc bu gibi durumlarda yineleyicileri geçersiz kılar.
ShreevatsaR

2

İşte cppreference.com'dan güzel bir özet tablo :

resim açıklamasını buraya girin

Buraya, ekleme , konteynere bir veya daha fazla eleman ekleyen herhangi bir yöntemi ve silme işlemi , bir veya daha fazla elemanı konteynırdan uzaklaştıran herhangi bir yöntemi belirtir.

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.