Yalnızca başlık kitaplıklarının avantajları


101

Yalnızca başlık kitaplığının faydaları nelerdir ve uygulamayı neden ayrı bir dosyaya koymaya karşı çıkarsınız?


Çoğunlukla şablonlar, ancak aynı zamanda dağıtımını ve kullanımını biraz daha kolaylaştıracaktır.
BoBTFish

4
Yalnızca başlık içeren bir kitaplığın dezavantajlarını sorunun kapsamına eklemek istiyorum ...
moooeeeep

Daha önce bahsedilmeyen olumsuz yönler nelerdir?
NebulaFox

7
@moooeeeep: Downsides, sen paragraf okumak isteyebilirsiniz "Dur kodunu inlining" in C ++ Dos ve Yapılmaması Gerekenler Krom Projeleri web sayfası.
Bay C64

Yanıtlar:


57

Yalnızca başlık içeren bir kitaplığın tek seçenek olduğu durumlar vardır, örneğin şablonlarla uğraşırken.

Yalnızca başlık içeren bir kitaplığa sahip olmak, kitaplığın kullanılabileceği farklı platformlar hakkında endişelenmenize gerek olmadığı anlamına da gelir. Uygulamayı ayırdığınızda, bunu genellikle uygulama ayrıntılarını gizlemek için yaparsınız ve kitaplığı başlıklar ve kitaplıkların ( lib, dll'ler veya .sodosyalar) bir kombinasyonu olarak dağıtırsınız . Bunların elbette destek sunduğunuz tüm farklı işletim sistemleri / sürümleri için derlenmesi gerekir.

Ayrıca uygulama dosyalarını da dağıtabilirsiniz, ancak bu kullanıcı için fazladan bir adım anlamına gelir - kitaplığınızı kullanmadan önce derlemek.

Elbette bu durum bazında geçerlidir. Örneğin, yalnızca başlık kitaplıkları bazen artarkod boyutu ve derleme süreleri.


6
"Yalnızca başlık içeren bir kitaplığa sahip olmak, kitaplığın kullanılabileceği farklı platformlar hakkında endişelenmenize gerek olmadığı anlamına da gelir": yalnızca kitaplığı korumanız gerekmiyorsa. Aksi takdirde, sahip olduğunuz materyal üzerinde yeniden üretemeyeceğiniz veya test edemeyeceğiniz hata raporlarıyla dolu bir kabustur.
James Kanze

1
Sadece başlığın performans avantajları hakkında benzer bir soru sordum. Gördüğünüz gibi kod boyutunda bir fark yok. Ancak, yalnızca başlık içeren örnek uygulama% 7 daha yavaş çalıştı. stackoverflow.com/questions/12290639/…
Homer6

@ Homer6 bana ping attığın için teşekkürler. Bunu aslında hiç ölçmedim.
Luchian Grigore

1
@LuchianGrigore Ben de olan başka birini bulamadım. Bu yüzden cevap vermem biraz zaman aldı. Pek çok spekülatif "kod boyutunu artırıyor" ve "bellek tüketimi" yorumları var. Sonunda, sadece bir örnek olsa bile, farklılıkların bir anlık görüntüsünü aldım.
Homer6

@ Homer6. Neden kod boyutunu artırmadı? Yalnızca kitaplık başlığını kullanan birden çok kitaplık oluşturduğunuzu ve ardından uygulamanızın, tek bir paylaşılan kitaplığa bağlanmak yerine birden çok kopyaya sahip olmanız gereken tüm bu kitaplıkları kullandığını varsayarsak.
pooya13

61

Yalnızca başlık kitaplığının avantajları:

  • Oluşturma sürecini basitleştirir. Kitaplığı oluşturmanıza gerek yoktur ve derlenmiş kitaplığı derlemenin bağlantı adımı sırasında belirtmeniz gerekmez. Derlenmiş bir kitaplığınız varsa, muhtemelen birden çok sürümünü oluşturmak isteyeceksiniz: Biri hata ayıklama etkin olarak derlenmiş, diğeri optimizasyon etkinleştirilmiş ve muhtemelen bir başkası da sembollerden arındırılmış. Ve belki çok platformlu bir sistem için daha da fazlası.

Yalnızca başlık içeren bir kitaplığın dezavantajları:

  • Daha büyük nesne dosyaları. Bazı kaynak dosyalarda kullanılan kitaplıktaki her satır içi yöntem, o kaynak dosya için derlenen nesne dosyasında zayıf bir sembol, satır dışı tanım da alır. Bu, derleyiciyi yavaşlatır ve ayrıca bağlayıcıyı yavaşlatır. Derleyicinin tüm bu şişkinliği oluşturması ve ardından bağlayıcının onu filtrelemesi gerekir.

  • Daha uzun derleme. Yukarıda bahsedilen şişkinlik sorununa ek olarak, derleme daha uzun sürecektir çünkü başlıklar, derlenmiş bir kitaplığa göre yalnızca başlık içeren bir kitaplıkla doğal olarak daha büyüktür. Bu büyük başlıkların, kitaplığı kullanan her kaynak dosya için ayrıştırılması gerekecek. Diğer bir faktör, yalnızca başlık içeren bir kitaplıktaki başlık dosyalarının #include, kitaplık derlenmiş bir kitaplık olarak oluşturulmuş olsaydı ihtiyaç duyulacak başlıkların yanı sıra satır içi tanımların ihtiyaç duyduğu başlıklara sahip olmasıdır.

  • Daha karışık derleme. Yalnızca başlık içeren bir kitaplıkta #includeihtiyaç duyulan fazladan dosyalar nedeniyle yalnızca başlık kitaplığıyla çok daha fazla bağımlılık elde edersiniz . Kitaplıktaki bazı temel işlevlerin uygulamasını değiştirin ve tüm projeyi yeniden derlemeniz gerekebilir. Derlenmiş bir kitaplık için kaynak dosyada bu değişikliği yapın ve tek yapmanız gereken o kitaplık kaynak dosyasını yeniden derlemek, derlenen kitaplığı bu yeni .o dosyasıyla güncellemek ve uygulamayı yeniden bağlamaktır.

  • İnsanın okuması daha zor. En iyi dokümantasyonla bile, bir kütüphanenin kullanıcıları çoğu zaman kütüphanenin başlıklarını okumaya başvurmak zorundadır. Yalnızca başlık içeren bir kitaplıktaki başlıklar, arabirimi anlama yoluna giren uygulama ayrıntılarıyla doldurulur. Derlenmiş bir kitaplıkla, tek gördüğünüz arayüz ve uygulamanın ne yaptığına dair kısa bir yorumdur ve genellikle tek istediğiniz budur. Gerçekten tüm istemen gereken bu. Kitaplığı nasıl kullanacağınızı bilmek için uygulama ayrıntılarını bilmeniz gerekmez.


22
Son nokta pek mantıklı değil. Herhangi bir makul dokümantasyon, işlev bildirimini, parametreleri, dönüş değerlerini vb. Ve ilgili tüm açıklamaları içerecektir. Başlık dosyasına başvurmanız gerekiyorsa, dokümantasyon başarısız olmuştur.
Thomas

6
@Thomas - En iyi profesyonel kütüphanelerde bile, çoğu zaman kendimi "iyi" başlığını okumaya başvurmak zorunda buluyorum. Aslında, sözde "iyi" dokümantasyon kod artı yorumdan çıkarılırsa, genellikle başlıkları okumayı severim. Kod artı yorumlar bana otomatik olarak oluşturulan belgelerden daha fazlasını anlatıyor.
David Hammen

2
Son nokta geçerli değil. Başlıklar zaten özel üyelerde uygulama ayrıntılarıyla doldurulmuştur, bu nedenle cpp dosyasının tüm uygulama ayrıntılarını gizlemesi gibi değildir. Ek olarak, C # gibi diller aslında tasarım gereği "yalnızca başlıktır" ve IDE ayrıntıları gizleme (onları "aşağı katlama") ile
ilgilenir

2
@Tomas: Katılıyorum, son nokta tamamen sahte. Yalnızca başlık kitaplıklarıyla arabirimi ve uygulamayı birbirinden ayrı tutabilirsiniz; sadece arayüz başlığına sahip olursunuz # uygulama ayrıntılarını içerir. Bu nedenle, Boost kitaplıklarında genellikle adlı bir alt dizin (ve ad alanı) bulunur detail.
Nemo

4
@Thomas: Katılmıyorum. Başlık dosyası genellikle dokümantasyon için gittiğim ilk yerdir. Başlık iyi yazılmışsa, genellikle harici belgelere ihtiyaç yoktur.
Joel Cornett

15

Bunun eski bir iş parçacığı olduğunu biliyorum, ancak kimse ABI arayüzlerinden veya belirli derleyici sorunlarından bahsetmedi. Ben de yapacağımı düşündüm.

Bu temelde, insanlara dağıtmak için bir başlık içeren bir kitaplık yazmanız veya kendinizi yeniden kullanmanız yerine her şeyi bir başlıkta bulundurmanız kavramına dayanır. Bir başlığı ve kaynak dosyalarını yeniden kullanmayı ve bunları her projede yeniden derlemeyi düşünüyorsanız, bu gerçekten geçerli değildir.

Temel olarak, C ++ kodunuzu derlerseniz ve bir derleyici ile bir kitaplık oluşturursanız, kullanıcı bu kitaplığı farklı bir derleyiciyle veya aynı derleyicinin farklı bir sürümüyle kullanmaya çalışır, ardından ikili uyumsuzluk nedeniyle bağlayıcı hataları veya garip çalışma zamanı davranışları alabilirsiniz.

Örneğin derleyici satıcıları, STL uygulamalarını sürümler arasında sıklıkla değiştirir. Bir kütüphanede std :: vektörü kabul eden bir fonksiyonunuz varsa, bu sınıftaki baytların kütüphane derlendiğinde düzenlendikleri şekilde düzenlenmesini bekler. Yeni bir derleyici sürümünde, satıcı std :: vector için verimlilik iyileştirmeleri yaptıysa, kullanıcının kodu farklı bir yapıya sahip olabilecek yeni sınıfı görür ve bu yeni yapıyı kitaplığınıza aktarır. Buradan her şey yokuş aşağı gidiyor ... Bu nedenle, STL nesnelerinin kütüphane sınırlarının ötesine geçmemesi tavsiye edilir. Aynısı C Çalışma Zamanı (CRT) türleri için de geçerlidir.

CRT hakkında konuşurken, kitaplığınız ve kullanıcının kaynak kodunun genellikle aynı CRT'ye bağlanması gerekir. Visual Studio ile kitaplığınızı Çok İş Parçacıklı CRT kullanarak oluşturursanız, ancak kullanıcı Çok İş Parçacıklı Hata Ayıklama CRT'sine bağlanırsa, kitaplığınız ihtiyaç duyduğu sembolleri bulamayabileceğinden bağlantı sorunları yaşarsınız. Hangi işlev olduğunu hatırlayamıyorum, ancak Microsoft Visual Studio 2015 için bir CRT işlevi satır içi yaptı. Aniden CRT kitaplığı değil, başlıkta yer aldı, bu nedenle bağlantı sırasında bulması beklenen kitaplıklar artık yapamadı ve bu bağlantı hataları oluşturdu. Sonuç olarak bu kitaplıkların Visual Studio 2015 ile yeniden derlenmesi gerekti.

Windows API kullanıyorsanız, ancak kitaplık kullanıcısına farklı Unicode ayarlarıyla derlerseniz, bağlantı hataları veya garip davranışlar da alabilirsiniz. Bunun nedeni, Windows API'nin Unicode veya ASCII dizelerini kullanan işlevlere sahip olmasıdır ve projenin Unicode ayarlarına göre doğru türleri otomatik olarak kullanan makrolar / tanımlar. Kitaplık sınırı boyunca yanlış türde bir dize geçirirseniz, çalışma zamanında işler bozulur. Veya programın ilk etapta bağlanmadığını fark edebilirsiniz.

Bu şeyler, nesneleri / türleri diğer üçüncü taraf kitaplıklarından (örneğin bir Eigen vektörü veya bir GSL matrisi) kitaplık sınırları boyunca geçirmek için de geçerlidir. 3. taraf kitaplığı, siz kitaplığınızı derlemeniz ve kullanıcınızın kodunu derlemesi arasındaki başlığını değiştirirse işler bozulacaktır.

Temelde güvenli olmak için kütüphane sınırlarından geçebileceğiniz tek şey türler ve Düz Eski Veriler (POD) şeklinde oluşturulmuştur. İdeal olarak, herhangi bir POD, kendi başlıklarınızda tanımlanan ve herhangi bir üçüncü taraf başlıklarına dayanmayan yapılarda olmalıdır.

Yalnızca başlık kitaplığı sağlarsanız, tüm kodlar aynı derleyici ayarlarıyla ve aynı başlıklara göre derlenir, bu nedenle bu sorunların çoğu ortadan kalkar (sizin ve kullanıcınızın kullandığı üçüncü kısmi kitaplıkların sürümünün API uyumlu olması koşuluyla).

Ancak, artan derleme süresi gibi yukarıda bahsedilen olumsuzluklar da vardır. Ayrıca bir işletmeyi yönetiyor olabilirsiniz, bu nedenle, herhangi birinin çalması durumunda tüm kaynak kodu uygulama ayrıntılarınızı tüm kullanıcılarınıza vermek istemeyebilirsiniz.


8

Ana "fayda", kaynak kodu göndermenizi gerektirmesidir, böylece makinelerde ve hiç duymadığınız derleyicilerde hata raporları elde edersiniz. Kitaplık tamamen şablonlar olduğunda, fazla seçeneğiniz yoktur, ancak seçeneğiniz olduğunda yalnızca başlık genellikle kötü bir mühendislik seçeneğidir. (Öte yandan, elbette yalnızca başlık, herhangi bir entegrasyon prosedürünü belgelemeniz gerekmediği anlamına gelir.)


0

Satır içi, Bağlantı Süresi Optimizasyonu (LTO) ile yapılabilir

Yalnızca başlık kitaplıklarının iki ana avantajından birinin değerini azalttığı için bunu vurgulamak isterim: "satır içi olarak bir başlıkta tanımlara ihtiyacınız var".

Bunun minimal somut bir örneği şu adreste gösterilmektedir: Bağlantı zamanı optimizasyonu ve satır içi

Böylece sadece bir bayrak geçirirsiniz ve herhangi bir yeniden düzenleme çalışması yapmadan nesne dosyalarında satır içi yapılabilir, artık bunun için tanımları başlıklarda tutmaya gerek yoktur.

LTO'nun da kendi dezavantajları olabilir: Bağlantı zamanı optimizasyonunu (LTO) kullanmamanın bir nedeni var mı?

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.