Neden std :: string karşısında bu kadar çok string sınıfı var?


56

Bana göre daha büyük birçok C ++ kütüphanesi kendi string tipini oluşturuyor. İstemci kodunda sen (kütüphaneden birini kullanmak zorunda ya QString, CString, fbstringveya çoğu zaman gerektirir ki (standart tip ve biri arasında kütüphane kullanımlarını dönüştürme tutmak, kimsenin birkaç isim eminim vs.) en az bir kopya).

Öyleyse, belirli bir yanlışlık veya yanlış bir şey var mı std::string(tıpkı auto_ptranlambilim kötüydü gibi )? C ++ 11'de değişti mi?


32
Adı "Invented Here syndrome".
Cat Plus Plus,

10
@CatPlusPlus QString ve CString, ikisi de önceden yapılmış std :: string.
Robot

8
@Cat Plus Plus: Bu sendrom Java String sınıfını etkilemiyor gibi görünüyor.
Giorgio

20
@Giorgio: Java programcıları, dize sınıfları hakkında endişelenmek için dil eksiklikleri için geçici çözümler bulmakta çok meşguldü (bu arada Android yeniden düzenlendi.
Cat Plus Plus,

9
@Giorgio: Muhtemelen Java’nın kodlanmış sözdizimsel desteğinin java.lang.String(operatörün aşırı yüklenmesi, vb.) Başka bir şey kullanmayı çok acı verici yapmasıdır .
Mekanik salyangoz,

Yanıtlar:


57

Bu daha büyük C ++ kütüphanelerinin çoğu daha önce std::stringstandartlaştırılmıştı. Diğerleri, UTF-8 desteği ve kodlamalar arasında dönüşüm gibi geç standart hale getirilmiş veya hala standartlaştırılmamış ek özellikler içerir.

Bu kütüphaneler bugün uygulamaya konsaydı, muhtemelen std::stringörnekler üzerinde çalışan işlevler ve yineleyiciler yazmayı seçerlerdi .


5
UTF-8 desteği, C ++ 98'ten beri standartlaştırılmıştır. Böyle rahatsız edici ve kısmen bir uygulamada, kimsenin onu kullanamayacağı gibi görünen tanımlanmış bir şekilde
AProgrammer

9
@ APgramer: charherhangi bir UTF-8 kod noktasını tutacak kadar büyük olacağı garanti edilir. AFAIK, C ++ 98'in sağladığı tek "destek".
Ben Voigt

4
@AProgrammer: Bu destek gerçekten oldukça işe yaramaz.
DeadMG

4
Beri bu yerel ayar @AProgrammer tartışmalı kırık wchar_tolduğunu değil tüm Unicode kod noktalarını temsil etmek yeterince büyük. Dahası, UTF-16 ile ilgili tüm tartışmalar , UTF-8'in özel olarak kullanılması gerektiği konusunda çok zorlayıcı bir argümanın yapıldığı yerlerde zararlı olarak kabul edildi …
Konrad Rudolph

6
@KonradRudolph, orada kırılan yerel sistem değildir (wchar_t'un tanımı "desteklenen herhangi bir karakter kümesi için yeterince geniş"); 16 bite wchar_t işleyen sistemler aynı zamanda Unicode'u desteklememeyi taahhüt etti. Suçlu, önce 16 bite ihtiyaç duyan kod noktalarını asla kullanmayacağını garanti eden Unicode'dur, daha sonra 16 bite wchar_t işleyen sistemler, daha sonra 16 bite ihtiyaç duymak için unicode geçişi yapar.
AProgrammer

39

Dize C ++ 'ın büyük utancıdır.

İlk 15 yıl boyunca hiç bir string sınıf sunmuyorsunuz - her platformdaki her bir derleyiciyi ve her kullanıcıyı kendi oluşturmaya zorluyorsunuz.

Sonra bir dizge manipülasyon API'si veya sadece bir STL karakter kabı olup olmadığı, bir std :: Vector üzerinde olanları kopyalayan bazı algoritmalarla mı karıştırıldığı hakkında bir şeyler yaparsınız.

Replace () veya mid () gibi belirgin bir dize işleminde, ifadeyi tek bir sayfada uygun tutmak için yeni bir 'auto' anahtar kelimesi girmeniz gerekecek ve çoğu insanın tüm dilden vazgeçmesine yol açan bir yineleyici karışıklığı söz konusu olduğunda .

Ve sonra unicode 'support' ve std :: wstring'i sadece arghh aldınız.

teşekkür ederim - şimdi çok daha iyi hissediyorum.


12
@DeadMG - evet ve 1998'de, icat edildikten 15 yıl sonra ve MSFT bile kullandıktan 6 yıl sonra standardize edildi. Evet, yineleyiciler bir dizi yapmanın ve listenin aynı görünmesini sağlamanın yararlı bir yoludur, sence manipülasyon yapmanın açık bir yolu olduğunu düşünüyor musunuz?
Martin Beckett

3
C Sınıfları ile 1983 yılında icat edildi. C ++ değil. Yalnızca Standart kütüphaneler Standart tarafından belirlenir; bunlar, sizin için garip bir şekilde, yalnızca bir Standart'a sahip olduğunuzda gerçekleşebilir, bu nedenle herhangi bir Standart kitaplık için mümkün olan en erken tarih 1998'dir. Hepimiz yineleyicilerin aralıklara göre emdikleri için, ama bu gerçekten spesifik değil std::string. 1983 yılında bir String sınıfının olmayışı, şimdi daha fazla olmasını haklı çıkarmaz.
DeadMG

8
Düşüncelerim C ++ 'ın büyük utanç verici olduğunu düşünmüştüm ...
Doug T.

18
@DeadMG İnsanlar 1998'den önce uzun yıllar boyunca "C ++" diye bir şey kullanıyorlardı. İlk programımı 1985'te "C ++" diye bir şey kullanarak yazdım. ondan önce, kod yazıyorduk ve bir yerden dize sınıfı almak zorunda kalıyorduk. Bir zamanlar bu eski kod tabanlarına sahip olduktan sonra, bir standart elde ettiğimizde onları tam olarak dışarı atamaz ya da sıfırdan başaramazdık. Şimdi olması gereken, cfront ile gelen bir string sınıf olması gerektiğidir.
Robot'a

8
@DeadMG - ISO sertifikası olana kadar hiç kimse bir dil kullanmazsa, hiçbir zaman ISO'ya ulaşamayacağı için hiçbir dil kullanılmayacaktır. X86 assembler için ISO standardı yok ama platformu kullanmaktan mutluyum
Martin Beckett

32

Aslında ... ile ilgili birkaç sorun var std::stringve evet, C ++ 11'de biraz daha iyi hale geliyor, ama kendimizden daha önce öne çıkmayalım.

QStringve eski kütüphanelerin bir CStringparçasıdır , bu nedenle onlar C ++ 'nın standartlaştırılmasından önce (SGI STL gibi) var olmuşlardır. Böylece bir sınıf oluşturmak zorunda kaldılar.

fbstringçok spesifik performans kaygılarını ele alın. Standart bir arayüz sağlar ve algoritmik karmaşıklık minimumu garanti eder, ancak bunun hızlı olup olmadığına dair Uygulama Kalitesi ayrıntılarıdır. fbstringbelirli optimizasyonlara sahiptir (depolamaya bağlı veya findörneğin daha hızlı ).

Burada uyarılmayan diğer endişeler (en vrac):

  • C ++ 03 'te, deponun bitişik olması zorunlu değildir, C ile birlikte çalışabilirliği potansiyel olarak zorlaştırır. C ++ 11 bunu düzeltir.
  • std::string habersiz bir kodlama ve UTF-8 için özel bir kod içermiyor, UTF-8 dizesini içinde saklamak ve yanlışlıkla bozmak kolaydır
  • std::stringarayüz şişirilmiş , birçok yöntem serbest işlevler olarak uygulanmış olabilir ve birçoğu hem indeks tabanlı bir arayüze hem de yineleyici tabanlı bir arayüze uyacak şekilde çoğaltılır.

5
Endişe # 1 - C ++ 03 21.3.6 / 1 c_str(), bir miktar C-birlikte çalışabilirlik sağlayan bitişik depolamaya bir gösterici getiren garantiler . Ancak sivri verileri değiştiremezsiniz. Tipik geçici çözümler arasında a vector<char>.
John Dibling

@JohnDibling: Evet, ve başka bir sınırlama daha var: yeni tahsis edilen depoda bir kopyaya yol açabilir (Standart bunu yapmaz demez). Tabii ki C ++ 11 de kopyalamayı engellemiyor, fakat artık basitçe yapabileceğiniz &s[0]için artık önemli değil :)
Matthieu M.

1
@MatthieuM .: Şununla elde edilen işaretçi &s[0], NUL sonlandırılmış bir dizeye işaret etmeyebilir ( c_str()son değişiklikten bu yana çağrılmadıysa).
Ben Voigt

2
@ Malzeme: Başka bir tampon belleğe izin verilmiyor. " c_str()Döndürür: Her birinde olduğu pgibi bir işaretçi ". p + i == &operator[](i)i[0,size()]
Ben Voigt

3
Ayrıca dikkat edilmesi gereken, artık aklı başında hiç kimsenin MFC'yi kullanmamasıdır, bu yüzden CString'in modern C ++ 'da bir string sınıf olduğunu iddia etmek zor.
DeadMG

7

Burada yayınlanan sebeplerin yanı sıra, başka bir tane de ikili uygunluk bulunmaktadır . Kütüphanelerin yazarları, hangi std::stringuygulamayı kullandığınız ve onunkilerle aynı bellek düzenine sahip olup olmadığının kontrolü yoktur .

std::stringbir şablon olduğundan, uygulaması yerel STL başlıklarınızdan alınır. Şimdi, standart olarak tam uyumlu, performans açısından optimize edilmiş bazı STL versiyonlarını kullandığınızı hayal edin. Örneğin, std::stringdinamik ayırma sayısını ve önbellek eksikliğini azaltmak için her birine statik tampon girmeyi tercih etmiş olabilirsiniz . Sonuç olarak, uygulamanızın bellek düzeni ve / veya boyutu kütüphaneinkinden farklı.

Yalnızca düzen farklıysa, bazı std::stringüye işlevi kitaplıktan istemciye iletilen örnekler üzerinde çağrı yapar veya diğer üyeler hangi üyelerin kaydırıldığına bağlı olarak başarısız olabilir.

Eğer boyut da farklıysa, std::stringüyeli tüm kütüphane tipleri kütüphanede ve müşteri kodunda kontrol edildiğinde farklı boyutta görünecektir. std::stringÜyeyi takip eden veri üyeleri de ofsetlerde kaymış olacak ve müşteriden çağrılan herhangi bir doğrudan erişim / satır içi erişimci, kitaplığın kendisinde hata ayıklama yaparken "iyi görünmesine" rağmen çöpü geri getirecektir.

Sonuç olarak - eğer kütüphane ve müşteri kodu farklı std::stringversiyonlar için tekrar derlenirse , sadece gayet iyi bağlanırlar , ancak anlaşılması zor bazı hatalara yol açabilir. std::stringUygulamanızı değiştirirseniz, STL'den üye olan tüm kütüphanelerin, müşterinin std::stringdüzeniyle eşleşmesi için derlenmesi gerekir . Programcılar kütüphanelerinin sağlam olmasını istediklerinden, nadiren std::stringher yerde görülebildiğini göreceksiniz .

Adil olmak gerekirse, bu tüm STL tipleri için geçerlidir. IIRC'de standart bellek düzeni yoktur.


2
Bir * nix programcısı olmalısınız. C ++ ikili uyumluluğu tüm platformlarda eşit değildir ve özellikle veri üyeleri içeren Windows NO sınıflarında derleyiciler arasında taşınabilir.
Ben Voigt

(POD tipleri hariç demek istiyorum ve o zaman bile açık ambalajlama gereksinimlerine ihtiyaç duyuluyor)
Ben Voigt

1
Girişiniz için teşekkürler, farklı derleyici konuşmama rağmen, farklı STL konuşuyorum.
gwiazdorrr

1
+1: ABI, bir derleyici tarafından sağlanan sınıfın kendi versiyonunu kullanmanız için büyük bir neden. Yalnız bunun için, bunun kabul edilmiş bir cevap olmasını diliyorum.
Thomas Eding

6

Soruya birçok cevap var ama işte bazıları:

  1. Legacy. Dize kütüphanelerinin ve sınıflarının birçoğu std :: string varlığına PRIOR yazılmıştır.

  2. C koduyla uyumluluk için Kütüphane std :: string, C ++ ve C ++ ile çalışan diğer string kütüphanelerinin bulunduğu C ++ 'dır.

  3. Dinamik ayırmalardan kaçınmak için. Std :: string kütüphanesi dinamik ayırma kullanır ve gömülü sistemler, kesinti veya gerçek zamanlı kod ile ilgili ya da düşük seviye fonksiyonlar için uygun olmayabilir.

  4. Şablonlar. Std :: string kütüphanesi şablonlara dayanmaktadır. Oldukça yakın bir zamana kadar bir dizi C ++ derleyicisinin performansı düşük ya da hatta buggy şablon desteği vardı. Ne yazık ki, birçok özel araç kullanan bir sektörde çalışıyorum ve sektördeki büyük bir oyuncudan araç zincirlerimizden biri% 100 C + 'yı desteklemiyor.

Muhtemelen daha geçerli sebepler de var.


2
"Oldukça yakın zamanda" anlamı "Visual Studio bile onlar için oldukça makul bir desteğe sahip olduğundan on yıl geçti"?
DeadMG

@DeadMG - Visual Studio, dünyadaki uyumlu olmayan tek derleyici değil. Video oyunlarında çalışıyorum ve çoğunlukla piyasaya sürülmemiş donanım platformları için özel derleyiciler üzerinde çalışıyoruz (konsol döngülerinde veya yeni donanımlar göründüğünde birkaç yılda bir oluyor). "Oldukça yakın zamanda" bugün demek - Şu anda bazı derleyiciler şablonları iyi desteklemiyor. NDA'ları ihlal etmeden spesifik olamam ama şu anda C ++ desteğinin - özellikle şablon uyumluluğunun - "deneysel" olduğu düşünülen özel araçlara sahip bir platform üzerinde çalışıyorum.
Adisak

4

Çoğunlukla Unicode ile ilgilidir. Unicode için Standart destek en iyi şekilde berbattır ve herkesin kendi Unicode ihtiyacı vardır. Örneğin, ICU, isteyebileceğiniz her Unicode işlevselliğini destekliyor, muhtemelen Java tarafından üretilen otomatik olarak üretilen en iğrenç Java arayüzünün arkasında, hayal edebileceğiniz bir şey var ve Unix’te UTF-16’ya takılı kalmışsanız fikriniz olmayabilir. iyi zaman.

Ek olarak, birçok insan farklı seviyelerde Unicode desteğine ihtiyaç duyar - herkes karmaşık metin düzeni API'lerine ve bu tür şeylere ihtiyaç duymaz. Bu yüzden neden sayısız dizi sınıfının var olduğunu görmek kolaydır - Standart olan oldukça berbattır ve herkesin yeni olanlardan farklı ihtiyaçları vardır, hiç kimse hoş olmayan bir arayüzle çok sayıda Unicode desteği çapraz platform gerçekleştirebilen tek bir sınıf oluşturmayı başaramaz.

Kanımca, bu çoğunlukla C ++ Komitesinin Unicode'ye 1998 ya da 2003'te doğru destek vermemesinin suçudur, belki de anlaşılabilir bir durumdu , ama C ++ 11'de. Umarım C ++ 17'de daha iyisini yapacaklardır.


Merhaba, burada C ++ 20, Unicode desteğine ne oldu tahmin et?
Passer Tarafından

-4

Bunun nedeni, her programcının bir harika işlevi için kendi harika, daha hızlı string sınıfını yaratma gereğini kanıtlayacak ve hissettirdiği için. Bu genellikle biraz gereksiz ve deneyimimde her türlü fazladan dizilim dönüşümüne yol açıyor.


7
Bu doğru muydu, Java gibi dillerde başlı başına iyi bir uygulamanın bulunduğu benzer dize uygulamalarını görmeyi umuyordum.
Bill K

@BillK Java String'i kesindir, başka bir yere yeni bir işlevsellik koymalısınız.

Ve demek istediğim, final olmakla birlikte, 20 yıl boyunca hiç kimsenin özel bir dizgi yerleştirme yazdığını görmedim (Eh, dizge bitiştirme performansını iyileştirmeye çalıştım ama java dizeden + string'de çok daha akıllı. hayal edin)
Bill K

2
@Bill: Bunun farklı bir kültürle ilgisi olabilir. C ++ düşük seviyeli detayları anlamak isteyenler çekiyor. Java, işini başka birinin yapı taşlarını kullanarak yapmak isteyenler çekiyor. (Bunun, herhangi bir dili kullanmayı seçen herhangi bir birey hakkında değil, dilin ilgili tasarım hedefleri ve kültürü hakkında bir açıklama olduğunu unutmayın)
Ben Voigt
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.