Tampaknya ada pandangan yang berbeda tentang penggunaan 'using' sehubungan dengan namespace std.
Beberapa mengatakan gunakan ' using namespace std
', yang lain mengatakan jangan melainkan awalan fungsi std yang akan digunakan dengan ' std::
' sementara yang lain mengatakan gunakan sesuatu seperti ini:
using std::string;
using std::cout;
using std::cin;
using std::endl;
using std::vector;
untuk semua fungsi std yang akan digunakan.
Apa pro dan kontra dari masing-masing?
c++
namespaces
paoloricardo
sumber
sumber
Jawaban:
Sebagian besar pengguna C ++ cukup senang membaca
std::string
,std::vector
dll. Faktanya, melihat mentahvector
membuat saya bertanya-tanya apakah ini adalahstd::vector
definisi pengguna atau yang berbedavector
.Saya selalu menentang penggunaan
using namespace std;
. Ini mengimpor semua jenis nama ke dalam namespace global dan dapat menyebabkan segala macam ambiguitas yang tidak jelas.Berikut adalah beberapa pengenal umum yang ada di
std
namespace: count, sort, find, equal, reverse. Memiliki variabel yang disebut lokalcount
berarti bahwausing namespace std
tidak akan memungkinkan Anda untuk menggunakancount
bukanstd::count
.Contoh klasik dari konflik nama yang tidak diinginkan adalah seperti berikut ini. Bayangkan Anda seorang pemula dan tidak tahu tentang
std::count
. Bayangkan Anda menggunakan sesuatu yang lain<algorithm>
atau ditarik oleh tajuk yang tampaknya tidak berhubungan.Kesalahan biasanya panjang dan tidak bersahabat karena
std::count
merupakan template dengan beberapa tipe bersarang yang panjang.Ini tidak masalah, karena
std::count
masuk ke namespace global dan jumlah fungsi menyembunyikannya.Mungkin sedikit mengejutkan, ini tidak masalah. Pengenal yang diimpor ke dalam cakupan deklaratif muncul di ruang nama umum yang melingkupi tempat mereka didefinisikan dan di mana mereka diimpor. Dengan kata lain,
std::count
terlihat seperticount
pada namespace global, tetapi hanya di dalamincrement
.Dan untuk alasan serupa,
count
ambigu di sini.using namespace std
tidak menyebabkanstd::count
, sembunyikan bagian luarcount
seperti yang diharapkan. Theusing namespace
Aturan berarti bahwastd::count
penampilan (dalamincrement
fungsi) seolah-olah itu dideklarasikan di lingkup global, yaitu pada ruang lingkup yang sama sepertiint count = 0;
dan karenanya menyebabkan ambiguitas.sumber
using std::xxx;
. Itu tidak menyebabkan polusi namespace, menulis kode akan lebih pendek dan saya pikircopy
lebih banyak dibaca daripadastd::copy
.Mengecualikan dasar-dasar (Harus menambahkan std :: infront dari semua objek / fungsi stl dan lebih sedikit kemungkinan konflik jika Anda tidak memiliki 'using namespace std')
Perlu juga dicatat bahwa Anda tidak boleh menaruh
Dalam file header, karena file header dapat menyebar ke semua file yang menyertakan file header tersebut, meskipun mereka tidak ingin menggunakan namespace tersebut.
Dalam beberapa kasus, sangat bermanfaat untuk menggunakan hal-hal seperti
Seolah-olah ada versi swap khusus, kompiler akan menggunakannya, jika tidak maka akan kembali aktif
std::swap
.Jika Anda menelepon
std::swap
, Anda selalu menggunakan versi dasar, yang tidak akan memanggil versi yang dioptimalkan (jika ada).sumber
using std::swap
(yang merupakan satu-satunya hal yang pernah saya gunakan).u n s
dapat menyebar. Hanya untuk dicatat bahwa itu juga bisa masuk ke dalam header yang dibangun dengan benar: Mereka hanya harus dimasukkan setelah header nakal.swap
ataumove
(atauhash
,less
dll.), Anda harus memasukkan spesialisasi itu kenamespace std
dalamnya. Misalnya:namespace std {template<> class hash<X> {public: size_t operator()(const X&) const};} class X: {friend size_t std::hash<X>::operator()(const X&)};
Pertama, beberapa terminologi:
using std::vector;
using namespace std;
Saya pikir menggunakan direktif penggunaan baik-baik saja, selama mereka tidak digunakan pada lingkup global di file header. Jadi memiliki
dalam file .cpp Anda sebenarnya tidak menjadi masalah, dan jika ternyata, itu sepenuhnya di bawah kendali Anda (dan bahkan dapat dicakup ke blok tertentu jika diinginkan). Saya tidak melihat alasan partiklar untuk mengacaukan kode dengan banyak
std::
kualifikasi - itu hanya menjadi sekumpulan gangguan visual. Namun, jika Anda tidak menggunakan sejumlah besar nama daristd
namespace di kode Anda, saya juga melihat tidak ada masalah dengan meninggalkan arahan. Ini tautologi - jika arahan tidak diperlukan, maka tidak perlu menggunakannya.Demikian pula, jika Anda bisa bertahan dengan beberapa menggunakan-deklarasi (daripada menggunakan-direktif ) untuk tipe spesifik di
std
namespace, maka tidak ada alasan Anda tidak boleh hanya membawa nama-nama spesifik itu ke namespace saat ini. Dengan cara yang sama, saya pikir itu akan menjadi gila dan kerumitan pembukuan untuk memiliki 25 atau 30 deklarasi penggunaan ketika satu petunjuk penggunaan akan melakukan trik dengan baik.Juga baik untuk diingat bahwa ada kalanya Anda harus menggunakan deklarasi menggunakan. Lihat "Item 25: Pertimbangkan dukungan untuk pertukaran non-lempar" Scott Meyers dari Effective C ++, Edisi Ketiga. Untuk memiliki fungsi generik dan templated menggunakan metode swap 'terbaik' untuk tipe berparameter, Anda perlu menggunakan pencarian yang bergantung pada deklarasi penggunaan dan argumen (alias pencarian ADL atau Koenig):
Saya pikir kita harus melihat idiom umum untuk berbagai bahasa yang menggunakan ruang nama secara signifikan. Misalnya, Java dan C # menggunakan banyak ruang nama (bisa dibilang lebih dari C ++). Cara yang paling umum digunakan dalam namespace dalam bahasa tersebut adalah dengan membawanya ke ruang lingkup saat ini secara massal dengan ekuivalen menggunakan direktif. Hal ini tidak menyebabkan masalah yang tersebar luas, dan beberapa kali masalah tersebut ditangani dengan basis 'pengecualian' dengan menangani nama yang dimaksud melalui nama yang sepenuhnya memenuhi syarat atau dengan aliasing - seperti yang dapat dilakukan di C ++.
Herb Sutter dan Andrei Alexandrescu mengatakan ini di "Item 59: Jangan tulis penggunaan namespace di file header atau sebelum #include" pada buku mereka, C ++ Coding Standards: 101 Rules, Guidelines, dan Best Practices:
Stroupstrup sering dikutip mengatakan, "Jangan mencemari namespace global", dalam "Bahasa Pemrograman C ++, Edisi Ketiga". Dia sebenarnya mengatakan itu (C.14 [15]), tetapi mengacu pada bab C.10.1 di mana dia mengatakan:
Dan bagaimana seseorang memiliki keuntungan yang sama sebagai 'pengguna malas nama global'? Dengan memanfaatkan arahan using, yang dengan aman membuat nama di namespace tersedia untuk cakupan saat ini.
Perhatikan bahwa ada perbedaan - nama dalam
std
namespace yang tersedia untuk cakupan dengan penggunaan yang tepat dari direktif penggunaan (dengan menempatkan direktif setelah#includes
) tidak mencemari namespace global. Itu hanya membuat nama-nama itu tersedia dengan mudah, dan dengan perlindungan berkelanjutan terhadap bentrokan.sumber
std::
kualifikasi tidak mengacaukan kode - ada cara lain untuk menghindarinya (menggunakan-deklarasi atau typedef biasanya melakukan triknya).using namespace std;
" direktif tidak mencegah Anda untuk menyatakan pengenal alami Anda 'list
' - hanya saja jika Anda melakukannya, Anda tidak dapat gunakan lebih lamastd::list
tanpa membuatnya memenuhi syarat. Itu tidak berbeda dengan jika tidak adausing namespace std;
perintah " ". Atau apakah saya melewatkan sesuatu?Jangan pernah menggunakan menggunakan namespace pada lingkup global dalam file header. Itu dapat menyebabkan konflik dan orang yang bertanggung jawab atas file tempat konflik muncul tidak memiliki kendali atas penyebabnya.
Dalam file implementasi, pilihan dipotong jauh lebih baik.
Menempatkan menggunakan namespace std membawa semua simbol dari namespace itu. Ini bisa merepotkan karena hampir tidak ada badan yang mengetahui semua simbol yang ada di sana (sehingga memiliki kebijakan tanpa konflik tidak mungkin diterapkan dalam praktiknya) tanpa membicarakan simbol yang akan ditambahkan. Dan standar C ++ memungkinkan sebuah header untuk menambahkan simbol dari header lain (yang C tidak mengizinkannya). Ini masih dapat bekerja dengan baik dalam praktiknya untuk menyederhanakan penulisan dalam kasus terkontrol. Dan jika terjadi kesalahan, itu terdeteksi di file yang bermasalah.
Menggunakan std :: name; memiliki keuntungan dari kesederhanaan penulisan tanpa risiko mengimpor simbol yang tidak dikenal. Biayanya adalah Anda harus mengimpor secara eksplisit semua simbol yang diinginkan.
Kualifikasi secara eksplisit menambah sedikit kekacauan, tetapi saya pikir itu adalah sedikit masalah dalam beberapa latihan.
Dalam proyek saya, saya menggunakan kualifikasi eksplisit untuk semua nama, saya menerima menggunakan std :: name, saya melawan penggunaan namespace std (kami memiliki juru bahasa lisp yang memiliki jenis daftar sendiri dan konflik adalah hal yang pasti).
Untuk ruang nama lain, Anda juga harus mempertimbangkan konvensi penamaan yang digunakan. Saya mengetahui sebuah proyek yang menggunakan namespace (untuk pembuatan versi) dan awalan pada nama. Melakukan
using namespace X
kemudian hampir tanpa risiko dan tidak melakukannya mengarah ke kode yang terlihat bodohPrefixNS::pfxMyFunction(...)
.Ada beberapa kasus di mana Anda ingin mengimpor simbol. std :: swap adalah kasus yang paling umum: Anda mengimpor std :: swap dan kemudian menggunakan swap tidak memenuhi syarat. Pencarian yang bergantung pada argumen akan menemukan swap yang memadai di namespace dari jenis tersebut jika ada dan kembali ke template standar jika tidak ada.
Edit:
Dalam komentarnya, Michael Burr bertanya-tanya apakah konflik itu terjadi di dunia nyata. Ini adalah contoh langsung yang nyata. Kami memiliki bahasa ekstensi dengan dialek cadel. Penerjemah kami memiliki file include, lisp.h yang berisi
Kami harus mengintegrasikan dan menyesuaikan beberapa kode (yang akan saya beri nama "mesin") yang terlihat seperti ini:
Jadi kami memodifikasi seperti ini:
Baik. Semuanya bekerja. Beberapa bulan kemudian, "module.h" diubah menjadi "list.h". Tes lulus. "modul" tidak dimodifikasi sedemikian rupa sehingga mempengaruhi ABI-nya, jadi pustaka "engine" dapat digunakan tanpa mengompilasi ulang penggunanya. Tes integrasi baik-baik saja. "Modul" baru diterbitkan. Kompilasi mesin berikutnya rusak ketika kodenya belum dimodifikasi.
sumber
Jika Anda tidak memiliki risiko konflik nama dalam kode Anda dengan std dan pustaka lain, Anda dapat menggunakan:
Tetapi jika Anda ingin mengetahui dengan tepat ketergantungan kode Anda untuk dokumentasi atau ada risiko konflik nama gunakan cara lain:
Solusi ketiga, jangan gunakan solusi ini dan tulis std :: sebelum setiap penggunaan dalam kode memberi Anda lebih banyak keamanan tetapi, mungkin sedikit beban dalam kode ...
sumber
Kedua
dan
tambahkan beberapa simbol (satu atau banyak) ke namespace global. Dan menambahkan simbol ke namespace global adalah sesuatu yang tidak boleh Anda lakukan di file header. Anda tidak memiliki kontrol siapa yang akan menyertakan header Anda, ada banyak header yang menyertakan header lain (dan header yang menyertakan header yang menyertakan header dan sebagainya ...).
Dalam implementasi file (.cpp) itu terserah Anda (hanya ingat untuk melakukannya setelah semua perintah #include). Anda hanya dapat memecahkan kode dalam file khusus ini, jadi lebih mudah untuk mengelola dan mencari tahu alasan konflik nama. Jika Anda lebih suka menggunakan std :: (atau prefiks lainnya, mungkin terdapat banyak namespace dalam proyek Anda) sebelum indentifiers, tidak apa-apa. Jika Anda ingin menambahkan pengenal yang Anda gunakan ke namespace global, tidak apa-apa. Jika Anda ingin membawa seluruh namespace di kepala Anda :-), terserah Anda. Meskipun efeknya terbatas pada unit kompilasi tunggal, itu dapat diterima.
sumber
Bagi saya, saya lebih suka menggunakan
::
bila memungkinkan.Saya benci menulis:
Mudah-mudahan, dengan C ++ 0x saya akan menulis ini:
Jika namespace sangat panjang,
sumber
++i
, bukani++
karena, jika itu didefinisikan, membuat salinan sementara iterator yang tidak perlu.Anda tidak boleh berada
using namespace std
di cakupan namespace di header. Juga, saya kira sebagian besar programmer akan bertanya-tanya kapan mereka melihatvector
ataustring
tidakstd::
, jadi menurut saya tidakusing namespace std
lebih baik. Oleh karena itu saya berdebat untuk tidak pernah menjadiusing namespace std
sama sekali.Jika Anda merasa harus, tambahkan deklarasi penggunaan lokal seperti
using std::vector
. Tetapi tanyakan pada diri Anda: Berapa harga ini? Sebaris kode ditulis sekali (mungkin dua kali), tetapi dibaca sepuluh, seratus atau ribuan kali. Upaya pengetikan yang disimpan dengan menambahkan deklarasi atau petunjuk penggunaan adalah marjinal dibandingkan dengan upaya membaca kode.Dengan pemikiran tersebut, dalam sebuah proyek sepuluh tahun lalu kami memutuskan untuk secara eksplisit memenuhi syarat semua pengenal dengan nama namespace lengkap mereka. Apa yang tampak canggung pada awalnya menjadi rutinitas dalam dua minggu. Sekarang, di semua proyek di seluruh perusahaan tidak ada lagi yang menggunakan arahan atau deklarasi. (Dengan satu pengecualian, lihat di bawah.) Melihat kode (beberapa MLoC) setelah sepuluh tahun, saya merasa kami telah membuat keputusan yang tepat.
Saya menemukan bahwa biasanya, mereka yang menentang pelarangan
using
biasanya belum mencobanya untuk satu proyek. Mereka yang telah mencoba, seringkali merasa lebih baik daripada menggunakan arahan / deklarasi setelah waktu yang sangat singkat.Catatan: Satu-satunya pengecualian adalah
using std::swap
yang diperlukan (terutama dalam kode generik) untuk mengambil kelebihan bebanswap()
yang tidak dapat dimasukkan ke dalamstd
namespace (karena kami tidak diizinkan untuk meletakkan kelebihanstd
fungsi ke dalam namespace ini).sumber
std
, tetapi tidak kelebihan beban. Maaf untuk brainfart itu. Saya akan mengoreksi postingan tersebut.using namespace
perintah itu adalah untuk mengetik ; sebaliknya, itu untuk membuat membaca lebih mudah, karena, seperti yang Anda katakan, kode itu harus dibaca lusinan, ratusan atau ribuan kali. Dan bagi sebagian orang, pembacaannya jauh lebih mudah dengan lebih sedikitstd::
kekacauan. Tapi itu mungkin karena kemampuan perseptif pribadi; beberapa orang menyaringnyastd::
atau bahkan membutuhkannya sebagai panduan (seperti serif), yang lain tersandung dan merasa seperti berada di jalan yang bergelombang.Namespaces menyimpan kode untuk mencegah kebingungan dan polusi tanda tangan fungsi.
Berikut demo lengkap dan terdokumentasi tentang penggunaan namespace yang benar :
Keluaran:
sumber
using namespace std
mengimpor kontenstd
namespace saat ini. Jadi, keuntungannya adalah Anda tidak perlu mengetikstd::
di depan semua fungsi namespace itu. Namun, mungkin saja Anda memiliki ruang nama berbeda yang memiliki fungsi dengan nama yang sama. Jadi, Anda mungkin tidak akan menelepon yang Anda inginkan.Menentukan secara manual mana yang ingin Anda impor
std
mencegah hal itu terjadi, tetapi dapat mengakibatkan daftar panjang penggunaan di awal file Anda, yang menurut beberapa pengembang akan jelek;)!Secara pribadi, saya lebih suka menentukan namespace setiap kali saya menggunakan fungsi, kecuali jika namespace terlalu panjang, dalam hal ini saya menggunakan beberapa di awal file.
EDIT: seperti yang dicatat dalam jawaban lain, Anda tidak boleh memasukkan
using namespace
file header, karena ini akan menyebar ke semua file termasuk header ini dan dengan demikian dapat menghasilkan perilaku yang tidak diinginkan.EDIT2: mengoreksi jawaban saya, terima kasih kepada komentar Charles.
sumber
using namespace std;
mengimpor kontenstd
namespace ke dalam namespace global. Itu tidak mengubah namespace default. Mendefinisikan sesuatu di namespace global setelah ausing namespace std
tidak akan secara ajaib memasukkannya ke dalamstd
namespace.Sama seperti di Java di mana Anda dapat menggunakan salah satunya dapat menyertakan java.util. * Atau cukup memilih setiap kelas satu per satu, itu tergantung gayanya. Perhatikan bahwa Anda tidak menginginkannya
using namespace std
di awal file / cakupan lebar karena Anda akan mencemari namespace dan mungkin mengalami bentrok, mengalahkan titik namespace. Tetapi jika Anda memiliki fungsi yang menggunakan banyak STL, itu mengacaukan kode untuk memiliki campuran sintaks prefiks dalam logika Anda dan Anda mungkin harus mempertimbangkan untuk menggunakan baikusing namespace std
(saat menggunakan berbagai kelas) atau individuusing
(saat menggunakan beberapa kelas sering).sumber
Diskusi ini akan aktif selama IDE yang Anda gunakan tidak cukup fleksibel untuk menampilkan atau menyembunyikan informasi persis yang Anda butuhkan.
Itu karena tampilan kode yang Anda inginkan bergantung pada tugas yang ada.
Saat membuat kode sumber, saya lebih suka melihat dengan tepat kelas mana yang saya gunakan: apakah itu
std::string
, atauBuzFlox::Obs::string
kelasnya?Saat mendesain aliran kontrol, saya bahkan tidak tertarik pada jenis variabel, tapi saya ingin fokus pada
if
's danwhile
' dancontinue
's.Jadi ini saran saya:
Bergantung pada audiens kode Anda dan kekuatan alat Anda, pilih cara yang paling mudah dibaca, atau memberikan sebagian besar informasi.
sumber
Ada beberapa cara untuk memperbaikinya.
Pertama: gunakan seperti yang Anda lakukan.
Kedua: lakukan
namespace S = std;
, kurangi 2 karakter.Ketiga: gunakan
static
.Keempat: jangan gunakan nama yang
std
menggunakan.sumber
Satu-satunya alasan untuk meninggalkan std :: adalah bahwa Anda dapat, secara teori, menerapkan ulang semua fungsi STL sendiri. Kemudian fungsi Anda dapat dialihkan dari menggunakan std :: vector ke my :: vector tanpa mengubah kode.
sumber
Mengapa tidak misalnya
bukannya yang berat
Saya merasa jauh lebih mudah dibaca dan ini adalah standar saya untuk pengkodean.
Anda bahkan dapat menggunakannya untuk memasukkan beberapa informasi semantik untuk pembaca. Misalnya, pertimbangkan prototipe fungsi
yang mana nilai kembaliannya?
Bagaimana sebaliknya
sumber