Asumsi
Salah satu keuntungan dari perpustakaan header-only untuk C ++ adalah bahwa mereka tidak perlu dikompilasi secara terpisah.
Dalam C dan C ++
inline
masuk akal hanya jika fungsi didefinisikan dalam file header *.Secara tradisional, dalam tata letak C, .c / .h telah digunakan, di mana tajuk mewakili antarmuka publik minimal dari unit terjemahan. Demikian pula, .cpp / hpp.
Pertanyaan
Apakah perpustakaan hanya header umumnya lebih efisien kode-dan waktu pelaksanaan bijaksana daripada tata letak tradisional? Jika demikian, apakah ini karena inlining ekstensif atau optimasi lainnya?
* - mendefinisikan fungsi dalam header memungkinkan kompiler untuk melihat implementasi selama kompilasi dari setiap unit terjemahan dan secara praktis memungkinkan inlining kode
Jawaban:
Tidak, itu bukan keuntungan, justru sebaliknya - bagian utama perpustakaan harus dikompilasi sesering mungkin dimasukkan, bukan hanya sekali. Itu biasanya akan meningkatkan waktu kompilasi. Namun, jika Anda mengacu pada kelebihan yang tercantum di sini di Wikipedia : artikel itu berbicara tentang penurunan biaya administrasi terkait keseluruhan proses pembuatan, pengemasan, dan penyebaran.
Ini tergantung pada sistem compiler / linker, tapi saya kira untuk sebagian besar C dan C ++ compiler ini benar.
Itu sebagian besar benar. Header kelas C ++ sering mengandung lebih dari antarmuka publik minimal - mereka biasanya juga mengandung banyak hal pribadi. Untuk mengurangi ini, hal-hal seperti idiom PIMPL digunakan. Ini adalah sesuatu seperti "kebalikan" dari perpustakaan hanya header, ia mencoba untuk meminimalkan konten header yang diperlukan.
Tetapi untuk menjawab pertanyaan utama Anda: ini adalah kompromi. Semakin banyak kode pustaka yang dimasukkan ke file header, semakin banyak kompiler memiliki peluang untuk mengoptimalkan kode untuk kecepatan (jika ini benar-benar terjadi, atau jika peningkatannya terlihat, adalah pertanyaan yang sama sekali berbeda). Di sisi lain, terlalu banyak kode di header meningkatkan waktu kompilasi. Terutama dalam proyek-proyek C ++ besar ini dapat menjadi masalah serius, lihat "Skala Besar C ++ Desain Perangkat Lunak" oleh John Lakos - meskipun buku ini sedikit ketinggalan jaman dan beberapa masalah yang dijelaskan di sana ditangani oleh kompiler modern, ide-ide umum / solusi masih valid.
Khususnya, ketika Anda tidak menggunakan perpustakaan stabil (pihak ketiga), tetapi Anda sedang mengembangkan lib Anda sendiri selama proyek Anda, waktu kompilasi menjadi jelas. Setiap kali Anda mengubah sesuatu di lib, Anda harus mengubah file header, yang akan menyebabkan kompilasi ulang dan keterkaitan semua unit dependen.
IMHO popularitas lib header-saja disebabkan oleh popularitas pemrograman meta template. Untuk kebanyakan kompiler, templated libs harus header-only karena compiler hanya dapat memulai proses kompilasi utama ketika parameter type disediakan, dan untuk kompilasi dan optimisasi penuh kompiler harus melihat "keduanya sekaligus" - kode perpustakaan ditambah templat nilai parameter. Itu membuat tidak mungkin (atau paling tidak sulit) untuk menghasilkan unit kompilasi yang "dikompilasi" untuk perpustakaan seperti itu.
sumber
Baiklah, mari kita hancurkan beberapa asumsi Anda:
Mengompilasi sesuatu secara terpisah berarti berpotensi tidak harus mengkompilasi ulang semuanya jika hanya sebagian yang berubah.
Jadi, kerugian bukannya keuntungan.
Ya, satu-satunya efek yang
inline
tersisa adalah pengecualian pada aturan satu definisi .Celakalah kamu, jika definisi itu berbeda dalam cara apa pun.
Jadi, jika fungsi internal ke unit kompilasi, tandai
static
. Itu juga membuat inlining lebih mungkin, karena fungsi harus tersedia untuk menyelaraskannya.Namun, lihat optimasi tautan-waktu, yang didukung oleh setidaknya MSVC ++, gcc, dan dentang.
Ya, hanya menghadirkan antarmuka minimal yang merupakan salah satu tujuan, untuk mencapai stabilitas API dan ABI yang lebih tinggi, dan untuk meminimalkan waktu kompilasi.
Khususnya kelas C ++ tidak benar-benar diarahkan untuk itu, karena semua bit pribadi bocor ke header, seperti halnya yang dilindungi apakah Anda ingin mendapatkan dari itu atau tidak.
PIMPL desain-pola adalah untuk mengurangi detail tersebut.
Bagian di mana memisahkan antarmuka dan implementasi sepenuhnya gagal di C ++ adalah templat.
Panitia mencoba melakukan sesuatu dengan templat yang diekspor , tetapi yang telah ditinggalkan terlalu rumit dan tidak benar-benar berfungsi.
Sekarang, mereka bekerja pada sistem modul yang tepat , meskipun lambat. Itu sangat mengurangi waktu kompilasi, dan juga harus meningkatkan stabilitas API dan ABI dengan mengurangi permukaannya.
Pustaka khusus header dapat lebih efisien dalam ukuran kode dan waktu eksekusi, meskipun itu tergantung pada apakah pustaka dibagi, berapa banyak yang digunakan, dengan cara apa, dan apakah inlining membuktikan kemenangan yang menentukan dalam kasus tertentu.
Dan alasan inlining sangat penting untuk optimasi bukan karena inlining itu sendiri adalah dorongan yang besar, tetapi karena peluang untuk propagasi konstan dan optimasi lebih lanjut terbuka.
sumber