C ++ 11'de COW std :: string uygulamasının yasallığı


117

Anladığım kadarıyla, yazma üzerine kopyalamanın std::stringC ++ 11'de bir uyumu uygulamak için uygun bir yol olmadığını anladım, ancak son zamanlarda tartışmada ortaya çıktığında kendimi bu ifadeyi doğrudan destekleyemiyor buldum.

C ++ 11'in COW tabanlı uygulamalarını kabul etmediğini doğru muyum std::string?

Eğer öyleyse, bu kısıtlama yeni standartta (nerede) açıkça belirtilmiş mi?

Veya bu kısıtlama, std::stringCOW tabanlı bir uygulamayı engelleyen yeni gereksinimlerin birleşik etkisi olması anlamında ima ediliyor mu std::string? Bu durumda, 'C ++ 11'in COW tabanlı std::stringuygulamaları etkin bir şekilde yasaklayan' bir bölüm ve ayet tarzı türetilmesi ile ilgileneceğim .


Yanıtlar:


120

Buna izin verilmez, çünkü standart 21.4.1 p6 uyarınca, yineleyicilerin / referansların geçersiz kılınmasına yalnızca

- sabit olmayan temel_dize'yi bağımsız değişken olarak alan herhangi bir standart kitaplık işlevine bağımsız değişken olarak.

- [] operatörü, at, front, back, begin, rbegin, end ve rend dışında const olmayan üye işlevleri çağırma.

Bir COW dizesi için, const olmayanın çağrılması operator[], yukarıdaki paragrafta izin verilmeyen bir kopya oluşturmayı (ve başvuruları geçersiz kılmayı) gerektirir. Bu nedenle, C ++ 11'de bir COW dizesine sahip olmak artık yasal değildir.


4
Bazı mantık: N2534
MM

8
-1 Mantık su tutmaz. Bir COW kopyalama sırasında geçersiz kılınabilecek hiçbir referans veya yineleyici yoktur, kopyalamanın tüm amacı, bu tür referansların veya yineleyicilerin artık elde edilmesidir, bu nedenle kopyalama gereklidir. Ancak yine de C ++ 11 COW uygulamalarına izin vermiyor olabilir.
Şerefe ve hth. - Alf

11
@ Cheersandhth.-Alf: COW'a izin verildiyse mantık aşağıda görülebilir: std::string a("something"); char& c1 = a[0]; std::string b(a); char& c2 = a[1]; c1, a'ya referanstır. Sonra "kopyalarsınız" a. Daha sonra, referansı ikinci kez almaya çalıştığınızda, aynı arabelleğe işaret eden iki dizi olduğundan, const olmayan bir referans almak için bir kopya oluşturması gerekir. Bu, alınan ilk referansı geçersiz kılar ve yukarıda alıntılanan bölüme aykırıdır.
Dave S

9
@ Cheersandhth.-Alf göre bu , en azından GCC en İNEK uygulaması yok daves söylediğini tam olarak ne yapmak. Yani en azından bu tarz bir COW standart tarafından yasaklanmıştır.
Tavian Barnes

4
@Alf: Bu cevap, non-const operator[](1) 'in bir kopya yapması gerektiğini ve (2) bunun yasadışı olduğunu savunuyor . Bu iki noktadan hangisine katılmıyorsunuz? İlk yorumunuza bakıldığında, bir uygulamanın, en azından bu gereksinim altında, erişildiği zamana kadar dizeyi paylaşabileceği, ancak hem okuma hem de yazma erişimlerinin onu paylaşması gerekeceği görülüyor. Sebebin bu mu?
Ben Voigt

48

Tarafından cevaplar Dave S ve gbjbaanb olan doğru . (Ve Luc Danton da haklıdır, ancak bu onu yasaklayan orijinal kuraldan ziyade COW dizgilerini yasaklamanın bir yan etkisidir.)

Ancak bazı karışıklıkları gidermek için biraz daha açıklama ekleyeceğim. Çeşitli yorumlar , aşağıdaki örneği veren GCC bugzilla hakkındaki bir yorumuma bağlantı veriyor:

std::string s("str");
const char* p = s.data();
{
    std::string s2(s);
    (void) s[0];
}
std::cout << *p << '\n';  // p is dangling

Bu örneğin amacı, GCC'nin sayılan referans (COW) dizesinin C ++ 11'de neden geçerli olmadığını göstermektir. C ++ 11 standardı bu kodun düzgün çalışmasını gerektirir. Koddaki hiçbir şey pC ++ 11'de geçersiz kılınmasına izin vermez.

GCC eski referans sayılan kullanılarak std::stringuygulanması, bu kod, çünkü tanımsız davranışa sahip p olan sallantýdabir işaretçi haline geçersiz. ( s2Oluşturulduğunda veriyi paylaşır s, ancak const olmayan bir referans almak s[0], verilerin paylaşımının kaldırılmasını gerektirir, saynı zamanda "yazma sırasında bir kopya" s[0]da potansiyel olarak üzerine yazmak için kullanılabilir s, sonra s2gider kapsam dışı, ile gösterilen diziyi yok ederek p).

C ++ 03 standardı , 21.3 [lib.basic.string] p5'teki bu davranışadata() , ilk çağrının ardından gelen operator[]()işaretçileri, referansları ve yineleyicileri geçersiz kılabileceğini söyleyen bu davranışa açıkça izin verir . Dolayısıyla GCC'nin COW dizesi geçerli bir C ++ 03 uygulamasıydı.

C ++ 11 standardı artık bu davranışa izin vermez , çünkü hiçbir çağrı operator[](), bir çağrıyı takip edip etmediklerinden bağımsız olarak işaretçileri, referansları veya yineleyicileri geçersiz kılamaz data().

Yukarıdaki örnekte Yani mutlaka C ++ 11 iş ama değil ile çalışma libstdc ++ 'ın tür İNEK dize, inek dizesinin tür 11 C ++ izin verilmez nedenle o.


3
Çağrıda .data()(ve işaretçi, başvuru ya da yineleyicinin her dönüşünde) paylaşımı kaldıran bir uygulama bu sorundan zarar görmez. Yani (değişmez) bir arabellek herhangi bir zamanda paylaşılmaz veya harici referans olmadan paylaşılır. Bu örnek hakkındaki yorumu yorum olarak gayri resmi bir hata raporu olarak düşündüğünüzü sanıyordum, yanlış anladığım için çok üzgünüm! Ancak burada tarif ettiğim gibi, noexceptgereksinimler göz ardı edildiğinde C ++ 11'de iyi çalışan bu tür bir uygulamayı göz önünde bulundurarak görebileceğiniz gibi , örnek resmi hakkında hiçbir şey söylemiyor. İstersen kod verebilirim.
Şerefe ve hth. - Alf

7
Dizeye neredeyse her erişimi paylaşmazsanız, paylaşımın tüm avantajlarını kaybedersiniz. Bir COW uygulamasının, standart bir kitaplığın bunu kullanması için pratik olması gerekir std::stringve C ++ 11 geçersiz kılma gereksinimlerini karşılayan yararlı, yüksek performanslı bir COW dizesi gösterebileceğinizden içtenlikle şüpheliyim. Bu yüzden noexcept, son dakikada eklenen spesifikasyonların, altta yatan sebep değil, COW dizgilerinin yasaklanmasının bir sonucu olduğunu düşünüyorum. N2668 tamamen açık görünüyor, neden komitenin orada ana hatlarıyla belirtilen niyetinin açık kanıtlarını inkar etmeye devam ediyorsunuz?
Jonathan Wakely

Ayrıca, bunun data()bir const üye işlevi olduğunu unutmayın , bu nedenle diğer const üyeleriyle data()eşzamanlı olarak çağrı yapmak ve örneğin dizenin bir kopyasını oluşturan başka bir iş parçacığı ile eşzamanlı olarak çağrı yapmak güvenli olmalıdır . Yani her dizge işlemi için bir muteksin tüm ek yüküne ihtiyacınız olacak , hatta const olanlar veya kilitsiz değişken referans sayılan bir yapının karmaşıklığı ve tüm bunlardan sonra yalnızca hiçbir zaman değiştirmezseniz veya erişmezseniz paylaşabilirsiniz. dizeleriniz, pek çok dizginin referans sayısı bir olacaktır. Lütfen kodu girin, noexceptgarantileri göz ardı etmekten çekinmeyin .
Jonathan Wakely

2
Sadece bazı kodları bir araya getirerek, 129 basic_stringüye fonksiyonun yanı sıra ücretsiz fonksiyonlar olduğunu keşfettim . Soyutlama maliyeti: Bu manşet dışı optimize edilmemiş yeni sıfırıncı sürüm kodu, hem g ++ hem de MSVC ile% 50 ila% 100 daha yavaştır. İş parçacığı güvenliğini sağlamaz (yeterince kolay kaldıraç shared_ptr, sanırım) ve zamanlama amacıyla bir sözlüğün sıralanmasını desteklemek için yeterlidir, ancak modulo hataları basic_stringC ++ noexceptgereksinimleri dışında sayılan bir referansa izin verildiğini kanıtlar . github.com/alfps/In-principle-demo-of-ref-counted-basic_string
Şerefe ve


20

CoW, daha hızlı diziler yapmak için kabul edilebilir bir mekanizmadır ... ama ...

çoklu iş parçacığı kodlamayı daha yavaş hale getirir (tek yazmanın siz olup olmadığınızı kontrol etmek için tüm bu kilitleme, çok sayıda dizge kullanırken performansı düşürür). CoW'un yıllar önce öldürülmesinin ana nedeni buydu.

Diğer nedenler, []başka birinin değişmemesini beklediği bir dizenin üzerine yazmanız için herhangi bir koruma olmadan , operatörün size dize verilerini döndürmesidir. Aynısı c_str()ve için de geçerlidir data().

Hızlı google, çoklu okumanın temelde etkin bir şekilde izin verilmemesinin nedeni olduğunu söylüyor (açıkça değil).

Teklif şöyle diyor:

öneri

Tüm yineleyici ve öğe erişim işlemlerini aynı anda güvenli bir şekilde yürütülebilir hale getirmeyi öneriyoruz.

Sıralı kodda bile işlemlerin kararlılığını artırıyoruz.

Bu değişiklik, yazma üzerine kopyalama uygulamalarına etkin bir şekilde izin vermez.

bunu takiben

Yazma üzerine kopyalama uygulamalarından uzaklaşmadan kaynaklanan en büyük potansiyel performans kaybı, çok büyük çoğunlukla okuma dizelerine sahip uygulamalar için artan bellek tüketimidir. Ancak, bu uygulamalar için halatların daha iyi bir teknik çözüm olduğuna inanıyoruz ve Kütüphane TR2'ye dahil edilmek üzere bir halat önerisinin dikkate alınmasını tavsiye ediyoruz.

Halatlar , STLPort ve SGIs STL'nin bir parçasıdır.


2
Operatör [] sorunu gerçekten bir sorun değil. Sabit değişkeni koruma sağlar ve sabit olmayan değişken her zaman CoW'yi o anda yapma seçeneğine sahiptir (veya gerçekten çılgın olma ve onu tetiklemek için bir sayfa hatası ayarlama).
Christopher Smith

+1 Konulara gider.
Şerefe ve hth. - Alf

5
Lock_buffer () vb. ile std :: cow_string sınıfının dahil edilmemesi aptalca. Aslında çoğu zaman değil.
Erik Aronesty

Bir alternatif önerisini seviyorum, ipler. Başka alternatif türleri ve uygulamaları olup olmadığını merak ediyorum.
Voltaire

5

21.4.2 temel_string oluşturucularından ve atama işleçlerinden [string.cons]

basic_string(const basic_string<charT,traits,Allocator>& str);

[...]

2 Etkiler : basic_stringTablo 64'te belirtildiği gibi bir sınıf nesnesi oluşturur. [...]

Tablo 64, bu (kopya) kurucu aracılığıyla bir nesnenin inşasından sonra değerinin olduğunu yararlı bir şekilde belgelemektedir this->data():

str.data () ile ilk elemanı gösterilen dizinin ayrılmış bir kopyasının ilk elemanını gösterir

Diğer benzer yapıcılar için de benzer gereksinimler vardır.


+1 C ++ 11'in (en azından kısmen) COW'yi nasıl yasakladığını açıklar.
Şerefe ve hth. - Alf

Özür dilerim, yorgundum. Tampon şu anda paylaşılıyorsa, bir .data () çağrısının COW kopyalamayı tetiklemesi gerektiğinden başka bir şey açıklamaz. Yine de faydalı bir bilgi, bu yüzden olumlu oyların geçerli olmasına izin verdim.
Şerefe ve hth. - Alf

1

Artık dizelerin bitişik olarak depolanması garanti edildiğinden ve artık bir dizenin dahili depolamasına bir işaretçi almanıza izin verildiğinden (yani & str [0] bir dizi için olduğu gibi çalışır), kullanışlı bir COW yapmak mümkün değildir uygulanması. Çok fazla şey için bir kopya yapmanız gerekir. Sadece operator[]veya begin()const olmayan bir dizede kullanmak bile bir kopya gerektirir.


1
C ++ 11'deki dizelerin bitişik olarak saklanmasının garantili olduğunu düşünüyorum.
mfontanini

4
Geçmişte, tüm bu durumlarda kopyaları yapmak zorundaydınız ve bu bir sorun değildi ...
David Rodríguez - dribeas

@mfontanini evet, ama daha önce
değildiler

3
C ++ 11, dizelerin bitişik olduğunu garanti etse de, bu COW dizelerini yasaklamak için ortogonaldir. GCC'nin COW dizesi bitişiktir, bu nedenle açıkça "kullanışlı bir COW uygulaması yapmak mümkün değildir" iddianız sahte.
Jonathan Wakely

1
@supercat, destek deposunu istemek (örneğin arayarak c_str()) O (1) olmalıdır ve atamaz ve veri yarışlarını tanıtmamalıdır, bu nedenle tembel bir şekilde sıralarsanız bu gereksinimleri karşılamak çok zordur. Pratikte tek makul seçenek, her zaman bitişik verileri depolamaktır.
Jonathan Wakely

1

COW basic_string, C ++ 11 ve sonrasında yasaklanmış mıdır ?

ilişkin

C ++ 11'in COW tabanlı uygulamalarını kabul etmediğini doğru muyum std::string?

Evet.

ilişkin

Eğer öyleyse, bu kısıtlama yeni standartta (nerede) açıkça belirtilmiş mi?

Neredeyse doğrudan,bir COW uygulamasında dizi verilerininO ( n ) fiziksel olarak kopyalanmasınıgerektiren bir dizi işlem için sürekli karmaşıklık gereksinimleri nedeniyle.

Örneğin, üye işlevleri için

auto operator[](size_type pos) const -> const_reference;
auto operator[](size_type pos) -> reference;

… Bir COW uygulamasında, her ikisi de dize değerini paylaşmamak için dize verilerinin kopyalanmasını tetikler, C ++ 11 standardı

C ++ 11 §21.4.5 / 4 :

" Karmaşıklık: sabit zaman.

… Bu tür veri kopyalamayı ve dolayısıyla COW'u dışlayan.

C ++ 03 tarafından İNEK uygulamaları desteklenen değil bu sabit karmaşıklık gereksinimlerini sahip ve belirli kısıtlayıcı koşullar altında, tarafından çağrıları izin operator[](), at(), begin(), rbegin(), end(), veya rend(), yani dize öğelere atıfta invalidate referanslar, işaretçiler ve yineleyiciler için muhtemelen tabi a COW verileri kopyalanıyor. Bu destek C ++ 11'de kaldırılmıştır.


COW, C ++ 11 geçersiz kılma kuralları aracılığıyla da yasaklanmış mı?

Yazılırken çözüm olarak seçilen ve büyük ölçüde olumlu oy alan ve bu nedenle görünüşe göre inanılan başka bir cevapta,

Bir COW dizisi için, non const operator[]- çağrılması, bir kopya oluşturmayı (ve referansları geçersiz kılma) gerektirir; bu, yukarıdaki [C ++ 11 §21.4.1 / 6] paragrafında izin verilmeyen [alıntı]. Bu nedenle, C ++ 11'de bir COW dizesine sahip olmak artık yasal değildir.

Bu iddia iki ana yönden yanlış ve yanıltıcıdır:

  • Yanlış bir şekilde, yalnızca constöğe olmayan erişimcilerin bir COW veri kopyalamayı tetiklemesi gerektiğini belirtir .
    Ancak, constöğe erişimcilerinin de veri kopyalamayı tetiklemesi gerekir, çünkü istemci kodunun (C ++ 11'de) COW veri kopyalamayı tetikleyebilecek işlemler yoluyla daha sonra geçersiz kılmalarına izin verilmeyen referanslar veya işaretçiler oluşturmasına izin verirler.
  • Yanlış bir şekilde COW veri kopyalamanın referansın geçersiz kılınmasına neden olabileceğini varsayar.
    Ancak doğru bir uygulamada, COW veri kopyalama, dize değerinin paylaşılmasının kaldırılması, geçersiz kılınabilecek herhangi bir referansın olmadığı bir noktada yapılır.

Doğru bir C ++ 11 COW uygulamasının basic_stringnasıl çalışacağını görmek için, bunu geçersiz kılan O (1) gereksinimleri göz ardı edildiğinde, bir dizenin sahiplik ilkeleri arasında geçiş yapabileceği bir uygulama düşünün. Bir dize örneği, Politika Paylaşılabilir ile başlar. Bu politika etkinken harici öğe referansı olamaz. Örnek Benzersiz ilkeye geçiş yapabilir ve bir çağrıda olduğu gibi potansiyel olarak bir öğe başvurusu oluşturulduğunda .c_str()(en azından bu dahili arabelleğe bir işaretçi üretiyorsa) bunu yapması gerekir. Değerin sahipliğini paylaşan birden çok örnek olması durumunda, bu, dize verilerinin kopyalanmasını gerektirir. Bu Benzersiz politikaya geçişten sonra örnek, yalnızca atama gibi tüm referansları geçersiz kılan bir işlemle Paylaşılabilir'e geri dönebilir.

Dolayısıyla, cevabın COW dizgilerinin dışlandığı sonucu doğru olsa da, sunulan mantık yanlış ve kesinlikle yanıltıcıdır.

Bu yanlış anlaşılmanın nedeninin C ++ 11'in ek C'deki normatif olmayan bir not olduğundan şüpheleniyorum:

C ++ 11 §C.2.11 [diff.cpp03.strings], yaklaşık §21.3:

Değişiklik : basic_stringgereksinimler artık referans sayılan dizelere izin vermiyor.
Gerekçe: Geçersiz kılma, referans sayılan dizelerle biraz farklıdır. Bu değişiklik, bu Uluslararası Standart için davranışı (sic) düzenler.
Orijinal özellik üzerindeki etki: Geçerli C ++ 2003 kodu, bu Uluslararası Standartta farklı şekilde yürütülebilir

Buradaki mantık , C ++ 03 özel COW desteğini neden kaldırmaya karar verdiğinizi açıklıyor . Bu gerekçe, nedeni , standardın COW uygulamasına nasıl etkin bir şekilde izin vermediği değildir . Standart, O (1) gereksinimleri aracılığıyla COW'a izin vermez.

Kısacası, C ++ 11 geçersiz kılma kuralları COW uygulamasının std::basic_string. Ancak, g ++ 'nın standart kütüphane uygulamalarından en az birinde olduğu gibi, makul derecede verimli, kısıtlanmamış C ++ 03 tarzı bir COW uygulamasını ekarte ederler. Özel C ++ 03 COW desteği const, geçersiz kılma için ince, karmaşık kurallar pahasına, özellikle öğe erişimcileri kullanarak pratik verimliliğe izin verdi :

"İlk çağrı" COW desteğini içeren C ++ 03 §21.3 / 5 :

Bir basic_stringdizinin öğelerine atıfta bulunan referanslar, işaretçiler ve yineleyiciler , bu basic_stringnesnenin aşağıdaki kullanımları ile geçersiz kılınabilir :
- Üye olmayan işlevlere bir argüman olarak swap()(21.3.7.8), operator>>()(21.3.7.9) ve getline()(21.3. 7.9).
- Bir argüman olarak basic_string::swap().
- Arama data()ve c_str()üye fonksiyonları.
- olmayan çağrılması constdışında, üye işlevlerini operator[](), at(), begin(), rbegin(), end(), ve rend().
- formları dışında Yukarıdaki kullanımların herhangi biri için sonraki insert()ve erase()yineleyici dönüş olmayan ilk çağrı constelemanı fonksiyonları operator[](), at(), begin(), rbegin(),end(), veya rend().

Bu kurallar o kadar karmaşık ve incelikli ki, varsa birçok programcının kesin bir özet verebileceğinden şüpheliyim. Yapamadım.


O (1) gereksinimleri göz ardı edilirse ne olur?

Örneğin, C ++ 11 sabit zaman gereksinimleri operator[]göz ardı edilirse, COW for basic_stringteknik olarak uygulanabilir, ancak uygulaması zor olabilir.

COW veri kopyalamasına maruz kalmadan bir dizinin içeriğine erişebilen işlemler şunları içerir:

  • Üzerinden birleştirme +.
  • Üzerinden çıktı <<.
  • basic_stringStandart kütüphane işlevlerine bağımsız değişken olarak kullanmak .

İkincisi, standart kitaplığın uygulamaya özel bilgi ve yapılara dayanmasına izin verildiği için.

Ek olarak bir uygulama, COW veri kopyalamayı tetiklemeden dizi içeriklerine erişmek için çeşitli standart dışı işlevler sunabilir.

Bir ana komplike faktör 11 C ++ olmasıdır basic_stringöğe erişim zorunluluk tetik veri kopyalama (string verileri un paylaşımı) fakat için gereklidir atmak değil mesela C ++ 11 §21.4.5 / 3, “ atar: . Hiçbir şey”. Ve bu nedenle, COW veri kopyalama için yeni bir arabellek oluşturmak için sıradan dinamik ayırmayı kullanamaz. Bunu aşmanın bir yolu, belleğin gerçekte tahsis edilmeden rezerve edilebildiği özel bir yığın kullanmak ve ardından bir dize değerine her mantıksal referans için gerekli miktarı ayırmaktır. Böyle bir yığında ayırma ve ayırma işlemi sabit zaman olabilir, O (1) ve birinin önceden ayırmış olduğu miktarı tahsis etmek,noexcept. Standardın gerekliliklerine uymak için, bu yaklaşımla, her ayrı ayırıcı için böyle bir özel rezervasyon tabanlı yığın olması gerekeceği görülmektedir.


Notlar:
¹ constÖğe erişimcisi, istemci kodunun verilere bir referans veya işaretçi almasına izin verdiği için bir COW verisi kopyalamayı tetikler; bu, örneğin constöğe olmayan erişimci tarafından tetiklenen daha sonraki bir veri kopyalama ile geçersiz kılınmasına izin verilmez .


3
" Örneğiniz, C ++ 11 için yanlış uygulamaya iyi bir örnek. Muhtemelen C ++ 03 için doğruydu." Evet , örneğin amacı bu . C ++ 03'te yasal olan bir COW dizesini gösterir çünkü eski yineleyici geçersiz kılma kurallarını ihlal etmez ve yeni yineleyici geçersiz kılma kurallarını ihlal ettiği için C ++ 11'de yasal değildir. Ayrıca yukarıdaki yorumda aktardığım ifadeyle de çelişiyor.
Jonathan Wakely

2
Eğer deseydi paylaşılabilir değil başlangıçta paylaştı Ben savundu olmazdı. Başlangıçta bir şeyin paylaşıldığını söylemek kafa karıştırıcıdır. Kendisiyle mi paylaşılıyor? Kelimenin anlamı bu değil. Ama tekrar ediyorum: C ++ 11 yineleyici geçersiz kılma kurallarının, pratikte hiç kullanılmayan (ve kabul edilemez performansa sahip olan) bazı varsayımsal COW dizelerini yasaklamadığını iddia etme girişiminiz, kesinlikle COW dizisini yasakladıklarında pratikte kullanılan, biraz akademik ve anlamsız.
Jonathan Wakely

5
Önerilen COW dizeniz ilginç, ancak ne kadar yararlı olacağından emin değilim . Bir COW dizesinin amacı, iki dizginin yazılması durumunda yalnızca dizi verilerini kopyalamaktır. Önerilen uygulamanız, kullanıcı tanımlı herhangi bir okuma işlemi gerçekleştiğinde kopyalamayı gerektirir. Derleyici yalnızca bir okuma olduğunu bilse bile , yine de kopyalamalıdır. Ayrıca, Benzersiz bir dizenin kopyalanması, dize verilerinin bir kopyasına (muhtemelen bir Paylaşılabilir duruma) neden olur ve bu da COW'yi oldukça anlamsız hale getirir. Yani karmaşıklık garantileri olmadan, gerçekten berbat bir COW dizisi yazabilirsiniz .
Nicol Bolas

2
Dolayısıyla, teknik olarak karmaşıklığın garanti ettiği herhangi bir tür COW yazmanızı engelleyen şey olduğu konusunda haklıyken, gerçekten yararlı herhangi bir COW dizisi yazmanızı engelleyen gerçekten [basic.string] / 5'tir .
Nicol Bolas

4
@JonathanWakely: (1) Aldığınız soru soru değil. Soru şu: “C ++ 11'in COW tabanlı std :: string uygulamalarını kabul etmemesi konusunda haklı mıyım? Öyleyse, bu kısıtlama yeni standartta (nerede) bir yerde açıkça belirtilmiş mi? " (2) std::stringO (1) gerekliliklerini göz ardı eden bir COW'nin verimsiz olacağı fikriniz sizin fikrinizdir. Performansın ne olabileceğini bilmiyorum ama bence bu iddia, bu yanıtla ilgili herhangi bir alaka için değil, verdiği his, taşıdığı hisler için ileri sürülüyor.
Şerefe ve hth. - Alf

0

Her zaman değişmez inekleri merak ediyordum: İnek bir kez yaratıldığında, yalnızca başka bir ineğin görevlendirmesiyle değiştirilebilirim, dolayısıyla standartla uyumlu olacaktır.

Bugün basit bir karşılaştırma testi için denemeye vaktim oldu: her düğümün haritadaki tüm dizgelerin bir setini tuttuğu, dize / inek tarafından anahtarlanmış N boyutunda bir harita (NxN sayıda nesneye sahibiz).

~ 300 bayt boyutundaki dizelerle ve N = 2000 inekler biraz daha hızlıdır ve neredeyse büyük ölçüde daha az bellek kullanır. Aşağıya bakın, boyutlar kbs cinsindendir, b cinsi inekler içindir.

~/icow$ ./tst 2000
preparation a
run
done a: time-delta=6 mem-delta=1563276
preparation b
run
done a: time-delta=3 mem-delta=186384
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.