Saya pernah membaca bahwa ada beberapa optimasi kompiler saat menggunakan #pragma once
yang dapat menghasilkan kompilasi yang lebih cepat. Saya tahu itu tidak standar, dan karenanya bisa menimbulkan masalah kompatibilitas lintas platform.
Apakah ini sesuatu yang didukung oleh kebanyakan kompiler modern pada platform non-windows (gcc)?
Saya ingin menghindari masalah kompilasi platform, tetapi juga ingin menghindari pekerjaan ekstra dari penjaga cadangan:
#pragma once
#ifndef HEADER_H
#define HEADER_H
...
#endif // HEADER_H
Haruskah saya khawatir? Haruskah saya mengeluarkan energi mental lebih lanjut untuk ini?
c++
include-guards
Ryan Emerle
sumber
sumber
#pragma once
tampaknya menghindari beberapa masalah tampilan kelas di VS 2008. Saya sedang dalam proses menyingkirkan penjaga termasuk dan mengganti mereka semua dengan#pragma once
alasan ini.Jawaban:
Menggunakan
#pragma once
harus bekerja pada kompiler modern apa pun, tapi saya tidak melihat alasan untuk tidak menggunakan standar#ifndef
termasuk penjaga. Ini bekerja dengan baik. Satu peringatan adalah bahwa GCC tidak mendukung#pragma once
sebelum versi 3.4 .Saya juga menemukan bahwa, setidaknya pada GCC, ia mengenali standar
#ifndef
termasuk penjaga dan mengoptimalkannya , jadi seharusnya tidak lebih lambat dari itu#pragma once
.sumber
#pragma once
umumnya lebih cepat karena file tidak sedang diproses.ifndef/define/endif
tetap memerlukan preprocessing, karena setelah blok ini Anda dapat memiliki sesuatu yang dapat dikompilasi (secara teoritis)#ifndef FOO_BAR_H
, biasanya untuk file seperti "foo_bar.h". Jika nanti Anda mengganti nama file ini, haruskah Anda menyesuaikan guard sertakan agar sesuai dengan konvensi ini? Juga, jika Anda memiliki dua foo_bar.h yang berbeda di dua tempat yang berbeda di pohon kode Anda, Anda harus memikirkan dua simbol yang berbeda untuk masing-masing. Jawaban singkatnya adalah menggunakan#pragma once
dan jika Anda benar-benar perlu mengkompilasi di lingkungan yang tidak mendukungnya, maka lanjutkan dan tambahkan menyertakan penjaga untuk lingkungan itu.#pragma once
memang memiliki satu kelemahan (selain non-standar) dan itu adalah jika Anda memiliki file yang sama di lokasi yang berbeda (kami memiliki ini karena sistem build kami menyalin file di sekitar) maka kompiler akan berpikir ini adalah file yang berbeda.sumber
#ifdef
makro juga bisa berbeda.Saya berharap
#pragma once
(atau sesuatu seperti itu) telah ada dalam standar. Menyertakan penjaga bukanlah masalah besar (tetapi mereka tampaknya agak sulit untuk dijelaskan kepada orang-orang yang belajar bahasa itu), tetapi sepertinya gangguan kecil yang bisa dihindari.Bahkan, sejak 99,98% dari waktu,
#pragma once
perilaku adalah perilaku yang diinginkan, akan lebih baik jika mencegah beberapa pemasukan header secara otomatis ditangani oleh kompiler, dengan#pragma
atau sesuatu untuk memungkinkan termasuk ganda.Tetapi kami memiliki apa yang kami miliki (kecuali bahwa Anda mungkin tidak memiliki
#pragma once
).sumber
#import
arahan standar .Saya tidak tahu tentang manfaat kinerja tetapi pasti berhasil. Saya menggunakannya di semua proyek C ++ saya (diberikan saya menggunakan kompiler MS). Saya merasa ini lebih efektif daripada menggunakan
Itu melakukan pekerjaan yang sama dan tidak mengisi preprocessor dengan makro tambahan.
GCC mendukung
#pragma once
secara resmi pada versi 3.4 .sumber
GCC mendukung
#pragma once
sejak 3.4, lihat http://en.wikipedia.org/wiki/Pragma_once untuk dukungan kompiler lebih lanjut.Keuntungan besar yang saya lihat tentang penggunaan
#pragma once
sebagai lawan untuk menyertakan penjaga adalah untuk menghindari kesalahan salin / tempel.Mari kita hadapi itu: kebanyakan dari kita hampir tidak memulai file header baru dari awal, melainkan hanya menyalin yang sudah ada dan memodifikasinya sesuai kebutuhan kita. Jauh lebih mudah untuk membuat templat yang berfungsi menggunakan
#pragma once
alih-alih menyertakan penjaga. Semakin sedikit saya harus memodifikasi template, semakin sedikit kemungkinan saya mengalami kesalahan. Memiliki penjaga yang sama termasuk dalam file yang berbeda mengarah ke kesalahan kompiler aneh dan butuh beberapa waktu untuk mencari tahu apa yang salah.TL; DR:
#pragma once
lebih mudah digunakan.sumber
Saya menggunakannya dan saya senang dengan itu, karena saya harus mengetik jauh lebih sedikit untuk membuat header baru. Ini bekerja dengan baik untuk saya dalam tiga platform: Windows, Mac dan Linux.
Saya tidak memiliki informasi kinerja, tetapi saya percaya bahwa perbedaan antara #pragma dan penjaga menyertakan tidak akan ada artinya dibandingkan dengan lambatnya penguraian tata bahasa C ++. Itulah masalah sebenarnya. Cobalah untuk mengkompilasi jumlah file dan baris yang sama dengan kompiler C # misalnya, untuk melihat perbedaannya.
Pada akhirnya, menggunakan penjaga atau pragma, tidak masalah sama sekali.
sumber
Menggunakan '
#pragma once
' mungkin tidak memiliki efek apa pun (tidak didukung di mana-mana - meskipun semakin banyak didukung), jadi Anda harus tetap menggunakan kode kompilasi bersyarat, dalam hal ini, mengapa repot-repot dengan '#pragma once
'? Kompilator mungkin mengoptimalkannya. Itu tergantung pada platform target Anda. Jika semua target Anda mendukungnya, maka maju dan gunakan itu - tetapi itu harus menjadi keputusan sadar karena semua akan hancur jika Anda hanya menggunakan pragma dan kemudian port ke kompiler yang tidak mendukungnya.sumber
Manfaat kinerja adalah dari tidak harus membuka kembali file setelah #pragma pernah dibaca. Dengan penjaga, kompiler harus membuka file (yang dapat memakan waktu) untuk mendapatkan informasi yang seharusnya tidak termasuk konten lagi.
Itu adalah teori hanya karena beberapa kompiler secara otomatis tidak akan membuka file yang tidak memiliki kode baca, untuk setiap unit kompilasi.
Pokoknya, ini bukan kasus untuk semua kompiler, jadi idealnya #pragma harus dihindari untuk kode lintas-platform yang bukan standar sama sekali / tidak memiliki definisi dan efek standar. Namun, secara praktis, ini benar-benar lebih baik daripada penjaga.
Pada akhirnya, saran terbaik yang bisa Anda dapatkan untuk memastikan memiliki kecepatan terbaik dari kompiler Anda tanpa harus memeriksa perilaku masing-masing kompiler dalam hal ini, adalah menggunakan pragma sekaligus dan penjaga.
Dengan begitu Anda mendapatkan yang terbaik dari keduanya (cross-platform dan membantu kecepatan kompilasi).
Karena lebih lama untuk mengetik, saya pribadi menggunakan alat untuk membantu menghasilkan semua itu dengan cara yang sangat sumbu (Visual Assist X).
sumber
pragma
setelahifndef
? Apakah ada manfaatnya?Tidak selalu.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52566 memiliki contoh yang bagus tentang dua file yang dimaksudkan untuk disertakan, tetapi secara keliru dianggap identik karena cap waktu dan konten yang identik (bukan nama file yang identik) .
sumber
#pragma once
tidak standar, jadi apapun yang dikompilasi oleh kompiler adalah "benar". Tentu saja, maka kita dapat mulai berbicara tentang apa yang "diharapkan" dan apa yang "berguna".Menggunakan gcc 3.4 dan 4.1 pada pohon yang sangat besar (kadang-kadang memanfaatkan distcc ), saya belum melihat kecepatan ketika menggunakan #pragma sekali sebagai pengganti, atau dalam kombinasi dengan standar termasuk penjaga.
Saya benar-benar tidak melihat bagaimana nilainya berpotensi membingungkan versi gcc lama, atau bahkan kompiler lain karena tidak ada penghematan nyata. Saya belum mencoba semua de-linter, tetapi saya berani bertaruh itu akan membingungkan banyak dari mereka.
Saya juga berharap itu telah diadopsi sejak awal, tetapi saya dapat melihat argumen "Mengapa kita membutuhkan itu jika ifndef bekerja dengan baik?". Mengingat banyak sudut dan kompleksitas C yang gelap, termasuk penjaga adalah salah satu hal yang paling mudah dan menjelaskan sendiri. Jika Anda bahkan memiliki sedikit pengetahuan tentang cara kerja preprosesor, mereka harus jelas.
Namun, jika Anda mengamati peningkatan yang signifikan, perbarui pertanyaan Anda.
sumber
Hari ini sekolah tua termasuk penjaga secepat pragma sekali. Bahkan jika kompilator tidak memperlakukan mereka secara khusus, itu akan tetap berhenti ketika melihat # jika andHATI APA dan APA yang didefinisikan. Membuka file sangat murah hari ini. Bahkan jika ada perbaikan, itu akan berada dalam urutan milidetik.
Saya hanya tidak menggunakan #pragma sekali, karena tidak memiliki manfaat. Untuk menghindari bentrok dengan penjaga menyertakan lainnya saya menggunakan sesuatu seperti: CI_APP_MODULE_FILE_H -> CI = Inisial Perusahaan; APP = Nama aplikasi; sisanya jelas.
sumber
Perbedaan utama adalah bahwa kompiler harus membuka file header untuk membaca guard include. Sebagai perbandingan, pragma pernah menyebabkan kompiler untuk melacak file dan tidak melakukan file IO ketika menemukan file lain termasuk untuk file yang sama. Meskipun itu kedengarannya dapat diabaikan, ia dapat dengan mudah ditingkatkan dengan proyek-proyek besar, terutama yang tanpa header yang baik termasuk disiplin ilmu.
Yang mengatakan, hari ini kompiler (termasuk GCC) cukup pintar untuk memperlakukan termasuk penjaga seperti pragma sekali. yaitu mereka tidak membuka file dan menghindari hukuman file IO.
Dalam kompiler yang tidak mendukung pragma saya telah melihat implementasi manual yang sedikit rumit ..
Saya pribadi suka pendekatan #pragma sekali karena menghindari kerumitan penamaan tabrakan dan kesalahan ketik potensial. Ini juga kode yang lebih elegan dengan perbandingan. Yang mengatakan, untuk kode portabel, tidak ada salahnya untuk memiliki keduanya kecuali jika kompiler mengeluh tentang hal itu.
sumber
#pragma once
sudah ada!Jika kita menggunakan msvc atau Qt (hingga Qt 4.5), karena GCC (hingga 3.4), msvc keduanya mendukung
#pragma once
, saya tidak dapat melihat alasan untuk tidak menggunakan#pragma once
.Nama file sumber biasanya sama dengan nama kelas, dan kami tahu, kadang-kadang kami perlu refactor , untuk mengganti nama kelas, maka kami harus mengubah
#include XXXX
juga, jadi saya pikir pemeliharaan manual#include xxxxx
bukanlah pekerjaan yang cerdas. bahkan dengan ekstensi Visual Assist X, mempertahankan "xxxx" bukanlah pekerjaan yang diperlukan.sumber
Catatan tambahan untuk orang-orang yang berpikir bahwa pemasukan file header secara otomatis satu kali saja selalu diinginkan: Saya membuat generator kode menggunakan inklusi file header ganda atau ganda sejak beberapa dekade. Khusus untuk pembuatan rintisan pustaka protokol saya merasa sangat nyaman untuk memiliki generator kode yang sangat portabel dan kuat tanpa alat dan bahasa tambahan. Saya bukan satu-satunya pengembang yang menggunakan skema ini karena blog ini menunjukkan X-Macros . Ini tidak akan mungkin dilakukan tanpa penjagaan otomatis yang hilang.
sumber
X-Macro
fitur ini, tetapi ini bukan penggunaan utama dari include, bukankah harus sebaliknya seperti header salut / # pragma multi jika kita ingin tetap KERING?