Apakah praktis untuk meninggalkan STL dalam pengembangan C ++? [Tutup]

19

Saya tahu di beberapa area (industri game, misalnya), STL tidak direkomendasikan. Jadi pertanyaan saya adalah: apakah benar-benar praktik yang baik untuk tidak menggunakan STL dalam beberapa kasus? Jika demikian, apa alasan terbesar untuk tidak menggunakan STL C ++ modern?

KaptenJH
sumber
pertanyaan terkait
fredoverflow
beberapa kolega saya berpendapat bahwa, iterator membuat debugging lebih sulit, karena kadang-kadang tidak mudah untuk masuk, dan ini juga berlaku untuk lambda. Apa tanggapan Anda?
KaptenJH
Adapun untuk melewatkan hal-hal selama debugging, lihat, misalnya: stackoverflow.com/questions/2062881/…
Martin Ba
Ini sepertinya pertanyaan yang bagus. Mungkin seseorang dapat menambahkan "Mengapa proyek memilih untuk tidak menggunakan STL?"
Matthew James Briggs

Jawaban:

25
  • Saya hanya bisa memikirkan satu alasan yang sahih dan itu sangat jarang: Waktu nyata yang sulit. Banyak hal di perpustakaan standar mengalokasikan memori secara internal dan itu tidak cukup deterministik untuk aplikasi real-time yang sulit, sehingga mereka harus dihindari. Aplikasi-aplikasi ini biasanya cukup sederhana, meskipun mereka membutuhkan waktu yang tidak proporsional untuk dikembangkan karena ulasan dan pengujian yang sangat ketat.

  • Saya dapat memikirkan satu alasan yang tidak valid, tetapi sangat umum: Pengembang yang tidak memahami kompleksitas komputasi, menyalahgunakan STL dan kemudian menyalahkan perpustakaan.

    STL biasanya lebih cepat saat runtime daripada solusi C-style dengan callback pointer atau solusi berbasis polimorfisme dengan metode virtual ( lihat juga keynote Bjarne Stroustrup ini ). Namun ketika pengembang tidak memahami spesifikasi kompleksitas yang diberikan dan menyalahgunakan perpustakaan dengan membuat sesuatu seperti vektor vektor dari beberapa objek kompleks (dalam C ++ 11, itu tidak lagi menjadi masalah!), Menyebabkan masalah kinerja dan kemudian membela diri dengan "Anda lihat, vektor agak lambat", ini dapat menyebabkan persepsi bahwa perpustakaan standar lambat. Dan begitu manajer mendapatkan persepsi seperti itu, ia dapat hidup sangat lama di dalam organisasi.

  • Jelas Anda tidak dapat menggunakan apa pun yang tidak didukung oleh platform yang Anda targetkan. Namun kami saat ini menargetkan empat platform seluler paling umum (Android, iOS, Bada, dan WinCE lama) dan menggunakan pustaka standar dan beberapa bagian Peningkatan pada semuanya.

    Banyak perpustakaan standar yang dulu tidak didukung oleh Microsoft di awal WinCE (IIRC iostreams hanya keluar dengan Visual Studio 2005), tetapi dimungkinkan untuk menggunakan STLport jauh sebelum itu sebagai gantinya. Dan Anda biasanya bisa mendapatkan itu untuk dikompilasi ke apa pun. Jadi saya akan menyebut alasan ini tidak valid juga.

    Selain itu, untuk waktu yang cukup lama itu bukan "STL", tetapi Perpustakaan Standar ANSI C ++. Itu didefinisikan oleh dokumen standar yang sama yang mendefinisikan bahasa itu sendiri. Apa pun yang tidak mendukungnya tidak benar-benar layak disebut C ++.

Jan Hudec
sumber
6
Argumen pertama (waktu nyata) tidak spesifik untuk bagian STL dari Perpustakaan Standar. sprintfsering mengalokasikan memori juga. Pada platform realtime, fungsi perpustakaan standar juga memiliki batas deterministik. Ini membuat implementasi C ++ realtime menjadi sulit: Anda harus hati-hati mengembangkan seluruh pustaka standar C ++, yang lebih berfungsi daripada hanya pustaka standar C kecil.
MSalters
@MSalters: Tentu, banyak hal yang tidak dapat digunakan di bawah persyaratan waktu nyata Bahkan beberapa fitur bahasa seperti pengecualian tidak bisa. Masih C ++ adalah bahasa yang bagus untuk sistem ini, karena dapat menggabungkan kinerja dan kontrol presisi dengan pengamanan yang kuat (RAII adalah fitur yang paling penting untuk itu).
Jan Hudec
@ JanHudec: Memang, itu sebabnya bagian STL hanya diperlukan untuk implementasi "host" dari C ++.
MSalters
7

Saya menggunakan STL dan meningkatkan selama bertahun-tahun. Jika saya ingin meninggalkannya dan menggunakan alat khusus saya, motivasinya adalah:

  1. Kompilasi pengurangan waktu (75%). Hanya dengan menyertakan iostreams dapat menambahkan 1 juta baris kode ke modul Anda. Ya header yang dikompilasi banyak membantu, tetapi masih memperlambat kompilasi dalam proyek-proyek besar. Dalam jangka panjang, ini menghabiskan banyak waktu bagi siapa pun yang mengerjakannya.
  2. Performa. (25%) STL ditulis untuk bekerja secara umum, tetapi Anda dapat mengoptimalkan struktur agar bekerja persis seperti yang Anda inginkan. Misalnya, Anda mungkin memiliki struktur data dengan jutaan string pendek. Mungkin jauh lebih cepat untuk menggunakan kelas string khusus berdasarkan prinsip boost :: small_vector (vektor data lokal statis kecil, alokasi dinamis hanya untuk string yang lebih besar), perubahan semacam ini dapat membuat bagian-bagian penting dari kode bekerja berkali-kali lebih cepat.
Marwin
sumber
1
SSO sudah umum.
Deduplicator
untuk anak cucu: SSO -> optimasi string kecil, yaitu kebanyakan (semua?) std :: implementasi string menyimpan string kecil di stack dan beralih ke heap jika perlu
blue
Waktu kompilasi adalah yang besar
user1754322
4

Ada satu alasan kuat untuk tidak menggunakan pustaka templat standar C ++: Salah satu platform target Anda tidak memiliki implementasi yang sepenuhnya sesuai (atau tidak ada implementasi sama sekali) dan Anda tahu bahwa itu tidak akan mendapatkan satu dalam tahun-tahun berikutnya.

Patrick
sumber
3
Aka "jangan menggunakannya saat kamu tidak memilikinya", itu masuk akal, sungguh. :)
Xeo
4
Mengingat bahwa pustaka standar C ++ 03 dirancang untuk diimplementasikan hanya dalam pustaka ANSI C89, apakah ada platform di mana Anda tidak bisa mendapatkan setidaknya STLPort ?
Jan Hudec
@ JanHudec Saya percaya ada platform tanpa STL karena mereka tidak memiliki cukup memori untuk menangani semuanya. Biasanya mereka juga kehilangan beberapa fungsionalitas C ++ lainnya (mis. Pengecualian).
Sulthan
2
@Sulthan: Untuk mikrokontroler saya agak mengerti, tetapi biasanya mereka termasuk dalam kategori "realtime yang sulit". Untuk hal lain, itu kebanyakan anggapan awal, karena STL biasanya sama efisiennya baik memori dan kinerja-bijaksana seperti kode kerajinan tangan. Banyak inlining dapat menyebabkan biner yang lebih besar, tetapi itu bahkan dapat dihindari dengan penerapan yang cermat dengan biaya kinerja tertentu (yang juga akan dihasilkan oleh solusi buatan tangan). Pengecualian yang hilang juga merupakan prakonsepsi, atau kemalasan, karena dibutuhkan upaya untuk mendefinisikan dan mengimplementasikan pengecualian ABI.
Jan Hudec
4

Saya tidak tahu tentang kerumitan (efisiensi implementasi) tetapi saya menggunakan kontainer Qt dan string secara ekstensif daripada yang std dan mereka bekerja dengan baik. Saya juga menemukan implementasi set dan daftar Qt lebih mudah digunakan.

Jadi, praktis untuk meninggalkan STL jika Anda dapat menggunakan perpustakaan lain yang sesuai dengan kebutuhan Anda.

Giorgio
sumber
2
padanan Qt dibuat kembali ketika tidak ada implementasi STL yang baik a) tersedia, atau b) ada gunanya. Itulah satu-satunya alasan mereka masih digunakan, tidak ada yang menentang STL hari ini.
gbjbaanb
1
@Iorgio: masalahnya ada di aplikasi yang kompleks, di mana Anda menggabungkan banyak pustaka. Wadah STL, sebagai standar, membentuk lingua franca . Lebih tepatnya, konvensi mereka yang melakukannya. Contoh paling terkenal adalah Boost. Ini dapat bekerja pada wadah STL. itu juga dapat bekerja pada kontainer Qt, tetapi hanya karena Qt telah mengikuti konvensi STL - misalnyaQList<T>::iterator
MSalters
3
Saya tidak mengundurkan diri, tetapi saya melihat satu alasan: Itu tidak menjawab pertanyaan. Anda mengatakan ada hal-hal yang harus digunakan daripada STL, baik-baik saja, tapi itu bukan alasan untuk menghindari STL. Selain alasan apa pun untuk menghindari STL, mungkin berlaku untuk Qt, MFC, dan perpustakaan lain semacam itu juga atau bahkan lebih.
Jan Hudec
3
@NoOne: Kami tahu Anda terbiasa dengan camelcase, bukan snakecase, tapi itu tidak membuat yang lebih buruk menjadi lebih buruk. Dan dari tiga nama fungsi yang Anda kritik, yang pertama adalah deskriptif sempurna untuk siapa pun yang ada hubungannya dengan c-string, dan dua lainnya diwarisi dari C, tidak akan membahasnya.
Deduplicator
1
@NoOne: Seperti yang saya katakan, saya benar-benar mengerti bahwa Anda lebih nyaman dengan CamelCase.
Deduplicator
3

Patrick telah menyebutkan alasan untuk tidak menggunakan seluruh STL, yaitu bahwa platform Anda tidak memilikinya.

Secara keseluruhan, saya pikir pertanyaannya tidak ada gunanya. Ini sebagian besar bukan keputusan semua atau tidak sama sekali, tetapi salah satu memilih dan memilih. Anda mungkin memutuskan untuk pergi dengan wadah dan algoritma, tetapi memutuskan untuk menggunakan sesuatu di luar Std Lib untuk string dan i / o.

Martin Ba
sumber
3

Ini tidak praktis, kecuali ada alasan kuat untuk melakukannya. Beberapa alasan seperti itu yang dapat saya pikirkan mencakup hanya sebagian atau kurang implementasi STL (atau bagian lain dari perpustakaan standar) atau keterbatasan sumber daya (memori, kecepatan CPU, penyimpanan, ...) yang harus Anda jalani dengan menggulung alat Anda sendiri yang mematuhi apa yang perlu Anda capai.

Dalam industri game sebagian besar (bahkan lebih kecil sampai batas tertentu) studio memiliki perpustakaan internal dan implementasi dari banyak bagian perpustakaan standar yang sangat disesuaikan untuk platform target dan dalam beberapa kasus menargetkan engnie atau bahkan game itu sendiri. Sederhananya ketika mengembangkan game untuk konsol, perangkat keras sangat dibatasi oleh standar saat ini. Ada ribuan dan ribuan garis perakitan kerajinan tangan karena suatu alasan. Sangat penting untuk meminimalkan semua jenis jejak kaki sumber daya dalam kode Anda sehingga permainan berjalan lebih cepat yang memungkinkan lebih banyak konten di dunia game (atau dunia yang lebih besar misalnya) yang diharapkan menghasilkan produk yang lebih baik.

"Setiap permainan yang berhasil dimulai dengan meluncurkan implementasi daftar tertaut milik Anda sendiri."

zxcdw
sumber
1
Saya akan membayangkan setiap permainan yang sukses dimulai dengan menulis kode menggunakan pustaka standar dan kemudian hanya mengoptimalkan kode begitu permainan telah diprofilkan secara luas. Mengoptimalkan sebelum Anda membuat profil data yang menyatakan apa yang perlu dioptimalkan tidak ada gunanya.
Cromulent
Benar. Ungkapan terakhir adalah hanya bermain di cara "kuno" menulis game di awal 90-an, ketika C ++ tidak begitu banyak digunakan dan perakitan + C adalah cara untuk pergi. Mungkin saya harus membuatnya lebih jelas. Ini berlaku baik untuk industri game di konsol, sebagian besar algorthm dan struktur data ditulis tangan secara default karena setiap byte dan siklus diperhitungkan (ya, bahkan dengan mengorbankan rawatan / portabilitas / apa pun).
zxcdw
2
Harus dikatakan, bahwa ini lebih merupakan pengalaman lama. Pengoptimal modern biasanya akan menghasilkan perakitan yang lebih baik dari kode yang dapat dipelihara sederhana daripada programmer akan melakukannya dengan tangan dan template generik seperti di STL atau Boost sering sejalan dengan kode yang efisien sebagai casing khusus semuanya dengan tangan. Tetapi ada banyak kode yang dimulai pada saat-saat ketika itu tidak terjadi dan banyak orang yang mempelajari perdagangan hari itu dan tetap bekerja seperti itu meskipun tidak masuk akal lagi.
Jan Hudec
2
@JanHudec Masalahnya adalah bahwa implementasi (dan perilaku juga, infact) harus sangat disesuaikan untuk tugas tersebut. Anda benar-benar tidak dapat menyisihkan beberapa lusin byte di sana-sini (merusak lokalitas referensi), mampir beberapa cabang untuk memvalidasi input (mispredicts cabang dan instruksi cache misses) dan menganggap bahwa kompiler tahu bagaimana membuat vektor struktur data Anda optimal untuk memanfaatkan SIMD (itu tidak akan, atau setidaknya Anda harus memverifikasi bahwa apa yang dicoba sudah benar). Tentu saja menulis perangkat lunak waktu nyata pada PC tidak seketat itu, Anda selalu dapat menggunakan CPU yang lebih cepat. Tidak di konsol.
zxcdw