Yalnızca başlık kitaplığının faydaları nelerdir ve uygulamayı neden ayrı bir dosyaya koymaya karşı çıkarsınız?
Yalnızca başlık kitaplığının faydaları nelerdir ve uygulamayı neden ayrı bir dosyaya koymaya karşı çıkarsınız?
Yanıtlar:
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 .so
dosyalar) 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.
Yalnızca başlık kitaplığının avantajları:
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 #include
ihtiyaç 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.
detail
.
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.
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.)
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ı?