Saya telah diberitahu oleh orang lain bahwa menulis using namespace std;
dalam kode salah, dan bahwa saya harus menggunakan std::cout
dan std::cin
langsung sebagai gantinya.
Mengapa using namespace std;
dianggap praktik yang buruk? Apakah tidak efisien atau berisiko mengambil risiko variabel ambigu (variabel yang memiliki nama yang sama dengan fungsi dalam std
namespace)? Apakah itu memengaruhi kinerja?
c++
namespaces
std
using-directives
c++-faq
akbiggs
sumber
sumber
std::literals::chrono_literals
,Poco::Data:Keywords
,Poco::Units
dan hal-hal yang akan menangani literal atau trik mudah dibaca. Setiap kali ada di header atau file implementasi. Mungkin OK dalam lingkup fungsi saya kira, tetapi selain dari literal dan hal-hal, itu tidak berguna.Jawaban:
Ini tidak terkait dengan kinerja sama sekali. Tetapi pertimbangkan ini: Anda menggunakan dua perpustakaan yang disebut Foo and Bar:
Semuanya berfungsi dengan baik, dan Anda dapat menelepon
Blah()
dari Foo danQuux()
dari Bar tanpa masalah. Tetapi suatu hari Anda meningkatkan ke versi baru Foo 2.0, yang sekarang menawarkan fungsi yang disebutQuux()
. Sekarang Anda mengalami konflik: Foo 2.0 dan Bar mengimporQuux()
ke namespace global Anda. Ini akan membutuhkan upaya untuk memperbaikinya, terutama jika parameter fungsi cocok.Jika Anda telah menggunakan
foo::Blah()
danbar::Quux()
, maka pengenalanfoo::Quux()
akan menjadi non-event.sumber
#define
adalah tidak membatasi dirinya sendiri pada ruang nama, tetapi menginjak seluruh basis kode. Alias namespace adalah yang Anda inginkan.Saya setuju dengan semua yang ditulis Greg , tetapi saya ingin menambahkan: Itu bahkan bisa lebih buruk dari yang dikatakan Greg!
Library Foo 2.0 dapat memperkenalkan fungsi,,
Quux()
yaitu kecocokan yang pasti lebih baik untuk beberapa panggilan AndaQuux()
daripadabar::Quux()
kode yang dipanggil selama bertahun-tahun. Kemudian kode Anda masih dikompilasi , tetapi secara diam-diam memanggil fungsi yang salah dan melakukan yang tahu-apa. Itu seburuk yang bisa didapat.Perlu diingat bahwa
std
namespace memiliki ton pengidentifikasi, banyak yang sangat yang umum (berpikirlist
,sort
,string
,iterator
, dll) yang sangat mungkin muncul dalam kode lain juga.Jika Anda menganggap ini tidak mungkin: Ada pertanyaan yang diajukan di sini di Stack Overflow di mana tepatnya hal ini terjadi (fungsi yang salah dipanggil karena
std::
awalan yang dihilangkan ) sekitar setengah tahun setelah saya memberikan jawaban ini. Ini adalah contoh lain dari pertanyaan semacam itu. Jadi ini adalah masalah nyata.Berikut ini satu lagi titik data: Banyak, bertahun-tahun yang lalu, saya juga merasa menjengkelkan karena harus mengawali semuanya dari pustaka standar
std::
. Kemudian saya bekerja di sebuah proyek di mana pada awalnya diputuskan bahwausing
arahan dan deklarasi dilarang kecuali untuk lingkup fungsi. Tebak apa? Sebagian besar dari kami memerlukan waktu beberapa minggu untuk membiasakan diri menulis awalan, dan setelah beberapa minggu lagi sebagian besar dari kami bahkan sepakat bahwa itu sebenarnya membuat kode lebih mudah dibaca . Ada alasan untuk itu: Apakah Anda suka prosa pendek atau lebih panjang adalah subjektif, tetapi awalan secara objektif menambah kejelasan kode. Bukan hanya kompiler, tetapi Anda juga merasa lebih mudah untuk melihat pengenal mana yang dirujuk.Dalam satu dekade, proyek itu tumbuh memiliki beberapa juta baris kode. Karena diskusi ini muncul berulang-ulang, saya pernah penasaran seberapa sering fungsi-lingkup (diperbolehkan)
using
sebenarnya digunakan dalam proyek. Saya mengambil sumber untuk itu dan hanya menemukan satu atau dua lusin tempat di mana itu digunakan. Bagi saya ini menunjukkan bahwa, setelah dicoba, pengembang tidak menemukanstd::
cukup menyakitkan untuk mempekerjakan menggunakan arahan bahkan setiap 100 kLoC bahkan di mana itu diizinkan untuk digunakan.Intinya: Mengawali secara eksplisit segala sesuatu tidak membahayakan, hanya membutuhkan sedikit waktu untuk membiasakan diri, dan memiliki keunggulan obyektif. Secara khusus, itu membuat kode lebih mudah untuk ditafsirkan oleh kompiler dan oleh pembaca manusia - dan itu mungkin harus menjadi tujuan utama saat menulis kode.
sumber
string
kelas standar , dan tampaknya setiap perpustakaan memiliki sendiri. Memberitahu Anda: Kami akan terus menulis kode kamistd::
, dan Anda dapat menjalankan kode kamigrep -v std:: | vim
saat menjelajahinya. Atau Anda dapat mengajarkan editor Anda bahwastd::
kata kunci yang akan diwarnai sama dengan warna latar belakang. Apapun yang berhasil.std::
berbahaya sama sekali. Ini membawa informasi yang sangat penting (yaitu "apa pun yang muncul setelah itu adalah bagian dari perpustakaan standar", dan itu masih awalan yang cukup pendek dan kompak. Sebagian besar waktu, tidak ada masalah sama sekali. Kadang-kadang, Anda memiliki beberapa baris kode di mana Anda perlu sering merujuk ke simbol spesifik dalamstd
namespace, dan kemudianusing
pernyataan dalam lingkup tertentu memecahkan masalah dengan baik. Namun dalam kasus umum, ini bukan noise, ia menyampaikan informasi berharga selain menghilangkan ambiguitasstd::
, saya tahu itu akan menjadi daristd::
tanpa harus memikirkannya. Jika saya melihatstring
ataulist
ataumap
sendiri, aku bertanya-tanya sedikit.vector
,transform
ataudistance
. Dan itu hanyalah contoh dari sekian banyak nama yang sangat umum digunakan di perpustakaan standar. Menyarankan untuk tidak menggunakannya karena takut atau pendapat bias dari fitur namespace yang merupakan bagian integral dari C ++ agak kontraproduktif.Masalah dengan menempatkan
using namespace
file header kelas Anda adalah bahwa hal itu memaksa siapa pun yang ingin menggunakan kelas Anda (dengan memasukkan file header Anda) juga menjadi 'menggunakan' (yaitu melihat semuanya) ruang nama lain tersebut.Namun, Anda mungkin merasa bebas untuk menempatkan pernyataan menggunakan dalam file * .cpp Anda.
Berhati-hatilah bahwa beberapa orang tidak setuju dengan pepatah saya "merasa bebas" seperti ini - karena meskipun
using
pernyataan dalam file cpp lebih baik daripada di header (karena itu tidak mempengaruhi orang-orang yang memasukkan file header Anda), mereka berpikir itu masih belum bagus (karena tergantung pada kode itu bisa membuat implementasi kelas lebih sulit untuk dipelihara). Entri C ++ Super-FAQ ini mengatakan,FAQ menyarankan dua alternatif:
Deklarasi menggunakan:
Cukup ketikkan std ::
sumber
Saya baru-baru ini mendapat keluhan tentang Visual Studio 2010 . Ternyata hampir semua file sumber memiliki dua baris ini:
Banyak fitur Boost masuk ke standar C ++ 0x, dan Visual Studio 2010 memiliki banyak fitur C ++ 0x, jadi tiba-tiba program-program ini tidak dikompilasi.
Oleh karena itu, menghindar
using namespace X;
adalah bentuk pemeriksaan masa depan, cara untuk memastikan perubahan ke perpustakaan dan / atau file header yang digunakan tidak akan merusak program.sumber
using
definisi fungsi di luar dan jarang menggunakanusing namespace
sama sekali.Versi singkat: jangan gunakan
using
deklarasi global atau arahan dalam file header. Jangan ragu untuk menggunakannya dalam file implementasi. Inilah yang dikatakan oleh Herb Sutter dan Andrei Alexandrescu tentang masalah ini dalam C ++ Coding Standards (huruf tebal untuk penekanan adalah milik saya):sumber
using
seharusnya tidak pernah muncul di header, saya tidak yakin tentang lisensi gratis untuk menempatkanusing namespace xyz;
di mana saja dalam kode Anda, terutama jikaxyz
itustd
. Saya menggunakanusing std::vector;
formulir, karena itu hanya menarik satu elemen dari namespace ke dalam lingkup pseudo-global, karena itu mengarah pada risiko tabrakan yang jauh lebih sedikit.using namespace
itu jahat, sepertigoto
kejahatan. Keduanya memiliki kegunaan yang valid, tetapi 999 kali dari 1000 mereka akan digunakan salah. Jadi, ya, denganusing namespace
di sumber Anda tidak akan mencemari namespace termasuk lainnya, rapi. Tapi itu masih tidak akan melindungi Anda dari "kesenangan" yang muncul dariusing namespace Foo
+using namespace Bar
dengan Anda menelepon (implisit Foo: :)baz(xyz)
dan tiba-tiba pemecah kode (tanpa perubahan terkait) hanya karenaBar::baz()
ditambahkan di suatu tempat, yang kebetulan menjadi lebih baik cocok (dan dengan demikian sekarang dipanggil sebagai gantinya)Seseorang seharusnya tidak menggunakan
using
arahan di lingkup global, terutama di header. Namun, ada situasi di mana itu sesuai bahkan dalam file header:Ini lebih baik daripada kualifikasi eksplisit (
std::sin
,std::cos
...), karena lebih pendek dan memiliki kemampuan untuk bekerja dengan tipe floating point yang ditentukan pengguna (melalui pencarian yang bergantung pada argumen (ADL)).sumber
using std::cos;
,,using std::sin
dll. Masalahnya adalah bahwa semua yang dirancang dengan baikuserlib
akan memilikisin
dancos
di dalam ruang nama mereka sendiri juga, jadi ini benar-benar tidak membantu Anda. (Kecuali adausing namespace userlib
sebelum template ini dan itu sama buruknyausing namespace std
- dan ruang lingkup di sana tidak terbatas.) Selain itu, satu-satunya fungsi seperti ini yang pernah saya lihat terjadi adalahswap
, dan dalam kasus seperti itu saya akan merekomendasikan hanya membuat template spesialisasistd::swap
dan menghindari seluruh masalah.template<typename T> void swap(MyContainer<T>&, MyContainer<T>&)
(Tidak ada fungsi spesialisasi sebagian template (FTPS), jadi kadang-kadang Anda perlu menggunakan overloading sebagai gantinya.x
memiliki satu atau lebih "ruang nama terkait" (misalnya jika itu didefinisikan dalamnamespace userlib
) maka setiap fungsi panggilan yang terlihat seperticos(x)
akan juga terlihat pada mereka ruang nama - tanpa apa punusing namespace userlib;
terlebih dahulu menjadi diperlukan. Zan Lynx benar (dan pencarian nama C ++ adalah byzantine ...)Jangan menggunakannya secara global
Itu dianggap "buruk" hanya jika digunakan secara global . Karena:
using namespace xyz
.using namespace std
Anda mungkin tidak menyadari semua hal yang Anda ambil - dan ketika Anda menambahkan yang lain#include
atau pindah ke revisi C ++ baru Anda mungkin mendapatkan konflik nama yang tidak Anda sadari.Anda dapat menggunakannya secara lokal
Silakan dan gunakan secara lokal (hampir) secara bebas. Ini, tentu saja, mencegah Anda dari pengulangan
std::
- dan pengulangan juga buruk.Sebuah idiom untuk menggunakannya secara lokal
Di C ++ 03 ada idiom - kode boilerplate - untuk mengimplementasikan
swap
fungsi untuk kelas Anda. Disarankan agar Anda benar-benar menggunakan lokalusing namespace std
- atau setidaknyausing std::swap
:Ini melakukan keajaiban berikut:
std::swap
untukvalue_
, yaituvoid std::swap(int, int)
.void swap(Child&, Child&)
, kompiler akan memilihnya.void std::swap(Child&,Child&)
dan mencoba yang terbaik untuk menukar ini.Dengan C ++ 11 tidak ada alasan untuk menggunakan pola ini lagi. Implementasi
std::swap
telah diubah untuk menemukan potensi kelebihan dan memilihnya.sumber
swap
di tempat pertama tidak begitu penting di C ++ 11 lagi, karenastd::swap
itu sendiri lebih fleksibel (menggunakan semantik bergerak). Tapistd::swap
secara otomatis memilih swap kustom Anda sendiri, itu benar-benar baru bagi saya (dan saya tidak benar-benar percaya).using std::swap;
daripadausing namespace std;
. Idiom yang lebih spesifik memiliki lebih sedikit efek samping dan karenanya membuat kode lebih dapat dipertahankan.swap
, dan berbagai tempat lain dalam standar diubah untuk mengatakan mereka memanggilswap
seperti itu (NB seperti yang dinyatakan di atas,using std::swap
adalah cara yang benar, bukanusing namespace std
). Tapistd::swap
itu dengan tegas tidak diubah untuk menemukan yang lainswap
dan menggunakannya. Jikastd::swap
dipanggil, makastd::swap
terbiasa.using std::swap
secara lokal, untuk mengurangi namespace lokal sementara pada saat yang sama membuat kode self-documenting. Anda jarang tertarik pada keseluruhan namespace std, jadi pilih saja bagian-bagian yang Anda minati.Jika Anda mengimpor file header yang tepat Anda tiba-tiba memiliki nama seperti
hex
,left
,plus
ataucount
dalam lingkup global Anda. Ini mungkin mengejutkan jika Anda tidak sadar yangstd::
berisi nama-nama ini. Jika Anda juga mencoba menggunakan nama-nama ini secara lokal, ini dapat menimbulkan kebingungan.Jika semua hal standar ada dalam ruang namanya sendiri, Anda tidak perlu khawatir tentang tabrakan nama dengan kode Anda atau perpustakaan lain.
sumber
distance
. masih saya lebih suka nama yang tidak memenuhi syarat di mana pun kemungkinan, karena itu meningkatkan keterbacaan bagi saya. ditambah, saya pikir kenyataan bahwa kita biasanya tidak memenuhi syarat dalam pidato lisan, dan bersedia untuk menghabiskan waktu menyelesaikan kemungkinan ambiguitas, berarti memiliki nilai untuk dapat memahami apa yang dibicarakan tanpa kualifikasi, dan diterapkan pada sumber kode itu berarti terstruktur sedemikian rupa sehingga jelas tentang semua itu tanpa kualifikasi.<iomanip>
. Tetap saja, poin bagus.Alasan lainnya adalah kejutan.
Jika saya melihat
cout << blah
, alih-alihstd::cout << blah
saya berpikir: Apa inicout
? Apakah ini normalcout
? Apakah ini sesuatu yang istimewa?sumber
cout
adalah contoh buruk karena semua orang mengenalinya. Tapi bayangkanfuture
di aplikasi keuangan. Apakah itu kontrak untuk membeli atau menjual sesuatu pada tanggal yang ditentukan? Bukan itu. Jika kode mengatakanstd::future
Anda tidak akan mudah bingung.Pemrogram berpengalaman menggunakan apa pun yang memecahkan masalah mereka dan menghindari apa pun yang menciptakan masalah baru, dan mereka menghindari arahan penggunaan tingkat file header untuk alasan yang tepat ini.
Pemrogram berpengalaman juga mencoba untuk menghindari kualifikasi penuh nama di dalam file sumber mereka. Alasan kecil untuk ini adalah bahwa tidak elegan untuk menulis lebih banyak kode ketika lebih sedikit kode cukup kecuali ada alasan yang bagus . Alasan utama untuk ini adalah mematikan pencarian yang bergantung pada argumen (ADL).
Apa alasan bagusnya ini ? Terkadang programmer secara eksplisit ingin mematikan ADL, di lain waktu mereka ingin ambigu.
Jadi, berikut ini OK:
sumber
Saya setuju bahwa itu tidak boleh digunakan secara global, tapi itu tidak terlalu jahat untuk digunakan secara lokal, seperti dalam a
namespace
. Berikut ini contoh dari "Bahasa Pemrograman C ++" :Dalam contoh ini, kami menyelesaikan bentrokan dan ambiguitas nama potensial yang muncul dari komposisi mereka.
Nama-nama yang secara eksplisit dideklarasikan di sana (termasuk nama yang dideklarasikan dengan menggunakan-deklarasi seperti
His_lib::String
) mengambil prioritas di atas nama-nama yang dapat diakses dalam lingkup lain dengan menggunakan-directive (using namespace Her_lib
).sumber
Saya juga menganggapnya sebagai praktik yang buruk. Mengapa? Hanya satu hari saya berpikir bahwa fungsi namespace adalah untuk membagi hal-hal, jadi saya tidak boleh merusaknya dengan membuang semuanya ke dalam satu tas global.
Namun, jika saya sering menggunakan 'cout' dan 'cin', saya menulis:
using std::cout; using std::cin;
di file .cpp (tidak pernah dalam file header seperti yang disebarkan dengan#include
). Saya berpikir bahwa tidak ada orang waras akan pernah nama sungaicout
ataucin
. ;)sumber
Sangat menyenangkan melihat kode dan tahu apa fungsinya. Jika saya melihat
std::cout
saya tahu itucout
aliranstd
perpustakaan. Jika saya melihatcout
maka saya tidak tahu. Itu bisa menjadicout
aliranstd
perpustakaan. Atau mungkin adaint cout = 0;
sepuluh baris yang lebih tinggi dalam fungsi yang sama. Ataustatic
variabel bernamacout
dalam file itu. Itu bisa apa saja.Sekarang ambil satu juta basis kode baris, yang tidak terlalu besar, dan Anda mencari bug, yang berarti Anda tahu ada satu baris dalam satu juta baris ini yang tidak melakukan apa yang seharusnya dilakukan.
cout << 1;
bisa membacastatic int
namacout
, menggesernya ke kiri sedikit, dan membuang hasilnya. Mencari bug, saya harus memeriksanya. Bisakah Anda melihat bagaimana saya benar-benar lebih suka melihatstd::cout
?Ini adalah salah satu dari hal-hal ini yang tampaknya ide yang sangat bagus jika Anda seorang guru dan tidak pernah harus menulis dan memelihara kode untuk mencari nafkah. Saya suka melihat kode di mana (1) Saya tahu apa fungsinya; dan, (2) saya yakin bahwa orang yang menulisnya tahu apa fungsinya.
sumber
Ini semua tentang mengelola kompleksitas. Menggunakan namespace akan menarik hal-hal yang tidak Anda inginkan, dan dengan demikian mungkin mempersulit proses debug (saya katakan mungkin). Menggunakan std :: all over the place lebih sulit untuk dibaca (lebih banyak teks dan semua itu).
Kuda untuk kursus - mengelola kompleksitas Anda bagaimana Anda bisa dan merasa mampu.
sumber
Mempertimbangkan
Perhatikan bahwa ini adalah contoh sederhana. Jika Anda memiliki file dengan 20 termasuk dan impor lainnya, Anda akan memiliki banyak dependensi untuk mencari tahu masalahnya. Yang lebih buruk dari itu adalah bahwa Anda bisa mendapatkan kesalahan yang tidak terkait dalam modul lain tergantung pada definisi yang bertentangan.
Itu tidak mengerikan, tetapi Anda akan menghemat sakit kepala dengan tidak menggunakannya dalam file header atau namespace global. Mungkin baik-baik saja melakukannya dalam lingkup yang sangat terbatas, tetapi saya tidak pernah memiliki masalah mengetik lima karakter tambahan untuk memperjelas dari mana fungsi saya berasal.
sumber
Anda harus dapat membaca kode yang ditulis oleh orang-orang yang memiliki gaya dan pendapat praktik terbaik yang berbeda dari Anda.
Jika Anda hanya menggunakan
cout
, tidak ada yang bingung. Tetapi ketika Anda memiliki banyak ruang nama yang terbang di sekitar dan Anda melihat kelas ini dan Anda tidak yakin apa fungsinya, memiliki namespace eksplisit bertindak sebagai komentar. Sekilas Anda dapat melihat, "oh, ini adalah operasi sistem file" atau "yang melakukan hal-hal jaringan".sumber
Menggunakan banyak namespace pada saat yang sama jelas merupakan resep untuk bencana, tetapi menggunakan JUST namespace
std
dan hanya namespacestd
bukanlah masalah besar menurut saya karena redefinisi hanya dapat terjadi oleh kode Anda sendiri ...Jadi anggap saja fungsinya sebagai nama yang dicadangkan seperti "int" atau "kelas" dan hanya itu.
Orang-orang harus berhenti bersikap anal tentang hal itu. Guru Anda benar selama ini. Cukup gunakan SATU namespace; itulah inti dari menggunakan namespace tempat pertama. Anda tidak seharusnya menggunakan lebih dari satu secara bersamaan. Kecuali jika itu milik Anda sendiri. Jadi sekali lagi, redefinisi tidak akan terjadi.
sumber
min
,end
danless
muncul distd::
namespace. Tetapi lebih dari itu, sekarang yangstd::
memiliki ribuan simbol di dalamnya, berguna bagi pembaca untuk mengetahui dari mana simbol baru yang mungkin tidak mereka ketahui berasal.Saya setuju dengan yang lain di sini, tetapi saya ingin mengatasi kekhawatiran tentang keterbacaan - Anda dapat menghindari semua itu dengan hanya menggunakan typedef di bagian atas file, fungsi, atau deklarasi kelas Anda.
Saya biasanya menggunakannya dalam deklarasi kelas saya karena metode dalam kelas cenderung berurusan dengan tipe data yang serupa (anggota) dan typedef adalah kesempatan untuk menetapkan nama yang bermakna dalam konteks kelas. Ini sebenarnya membantu keterbacaan dalam definisi metode kelas.
dan dalam implementasinya:
sebagai lawan:
atau:
sumber
Contoh nyata untuk mengklarifikasi masalah tersebut. Bayangkan Anda memiliki situasi di mana Anda memiliki dua perpustakaan,
foo
danbar
masing-masing memiliki ruang nama sendiri:Sekarang katakanlah Anda menggunakan
foo
danbar
bersama - sama dalam program Anda sendiri sebagai berikut:Pada titik ini semuanya baik-baik saja. Ketika Anda menjalankan program Anda, itu 'Melakukan sesuatu'. Tetapi kemudian Anda memperbarui
bar
dan katakanlah itu telah berubah menjadi seperti:Pada titik ini Anda akan mendapatkan kesalahan kompilator:
Jadi, Anda perlu melakukan pemeliharaan untuk mengklarifikasi maksud 'a'
foo::a
. Itu tidak diinginkan, tapi untungnya itu cukup mudah (cukup tambahkanfoo::
di depan semua panggilana
yang kompiler menandai sebagai ambigu).Tapi bayangkan skenario alternatif di mana bilah berubah sebagai gantinya:
Pada titik ini panggilan Anda untuk
a(42)
tiba - tiba mengikat,bar::a
bukan kefoo::a
alih dan bukannya melakukan 'sesuatu' itu melakukan 'sesuatu yang sama sekali berbeda'. Tidak ada peringatan kompiler atau apapun. Program Anda baru saja mulai melakukan sesuatu yang sama sekali berbeda dari sebelumnya.Ketika Anda menggunakan namespace Anda mempertaruhkan skenario seperti ini, itulah sebabnya orang tidak nyaman menggunakan namespace. Semakin banyak hal dalam namespace, semakin besar risiko konflik, sehingga orang mungkin lebih tidak nyaman menggunakan namespace
std
(karena jumlah hal dalam namespace itu) daripada ruang nama lain.Pada akhirnya ini adalah pertukaran antara kemampuan menulis vs keandalan / pemeliharaan. Keterbacaan dapat menjadi faktor juga, tetapi saya dapat melihat argumen untuk hal itu. Biasanya saya akan mengatakan keandalan dan rawatan lebih penting, tetapi dalam hal ini Anda akan terus membayar biaya penulisan untuk dampak keandalan / rawatan yang cukup langka. Trade-off 'terbaik' akan menentukan proyek Anda dan prioritas Anda.
sumber
Namespace adalah lingkup bernama. Ruang nama digunakan untuk mengelompokkan deklarasi terkait dan untuk memisahkan item yang terpisah. Misalnya, dua pustaka yang dikembangkan secara terpisah dapat menggunakan nama yang sama untuk merujuk ke item yang berbeda, tetapi pengguna masih dapat menggunakan keduanya:
Mengulang nama namespace dapat menjadi gangguan bagi pembaca dan penulis. Akibatnya, dimungkinkan untuk menyatakan bahwa nama-nama dari namespace tertentu tersedia tanpa kualifikasi eksplisit. Sebagai contoh:
Namespaces menyediakan alat yang ampuh untuk pengelolaan perpustakaan yang berbeda dan versi kode yang berbeda. Secara khusus, mereka menawarkan alternatif programmer bagaimana eksplisit untuk membuat referensi ke nama nonlokal.
Sumber: Tinjauan tentang Bahasa Pemrograman C ++ oleh Bjarne Stroustrup
sumber
Contoh di mana
using namespace std
melempar kesalahan kompilasi karena ambiguitas jumlah, yang juga merupakan fungsi dalam pustaka algoritma.sumber
::count
--masalah dipecahkan. Biasanya Anda akan memiliki lebih banyak barang dari std namespaced daripada dari tempat lain, ergo menjaga direktif namespace menggunakan mungkin menghemat Anda mengetik.Itu tidak membuat kinerja perangkat lunak atau proyek Anda lebih buruk. Dimasukkannya namespace di awal kode sumber Anda tidak buruk. Dimasukkannya
using namespace std
instruksi bervariasi sesuai dengan kebutuhan Anda dan cara Anda mengembangkan perangkat lunak atau proyek.The
namespace std
berisi fungsi standar C ++ dan variabel. Namespace ini berguna ketika Anda sering menggunakan fungsi standar C ++.Beberapa orang mengatakan itu adalah praktik buruk untuk memasukkan
using namespace std
dalam file sumber Anda karena Anda memohon dari namespace itu semua fungsi dan variabel. Ketika Anda ingin mendefinisikan fungsi baru dengan nama yang sama dengan fungsi lain yang terkandung dalamnamespace std
Anda akan membebani fungsi dan itu bisa menghasilkan masalah karena mengkompilasi atau mengeksekusi. Itu tidak akan dikompilasi atau dieksekusi seperti yang Anda harapkan.sumber
Saya tidak berpikir itu adalah praktik yang buruk dalam semua kondisi, tetapi Anda harus berhati-hati saat menggunakannya. Jika Anda menulis pustaka, Anda mungkin harus menggunakan operator resolusi lingkup dengan namespace untuk menjaga pustaka Anda dari menabrak kepala dengan perpustakaan lain. Untuk kode level aplikasi, saya tidak melihat ada yang salah dengannya.
sumber
"Mengapa 'menggunakan namespace std;' dianggap sebagai praktik buruk di C ++? "
Saya mengatakan sebaliknya: Mengapa mengetik lima karakter tambahan dianggap rumit oleh sebagian orang?
Pertimbangkan misalnya menulis perangkat lunak numerik. Mengapa saya bahkan mempertimbangkan untuk mencemari namespace global saya dengan memotong umum "std :: vector" ke "vector" ketika "vector" adalah salah satu konsep domain yang paling penting?
sumber
cout << hex << setw(4) << i << endl;
lebih mudah dibaca daripadastd::cout << std::hex << std::setw(4) << i << std::endl;
std::map<std::string,std::pair<std::string,std::string>>
mengerikan dibandingkan denganmap<string,pair<string,string>>
.Saya setuju dengan orang lain - itu meminta bentrokan nama, ambiguitas dan kemudian faktanya kurang eksplisit. Sementara saya bisa melihat penggunaan
using
, preferensi pribadi saya adalah untuk membatasi. Saya juga akan sangat mempertimbangkan apa yang beberapa orang tunjukkan:Jika Anda ingin menemukan nama fungsi yang mungkin merupakan nama yang cukup umum, tetapi Anda hanya ingin menemukannya di
std
namespace (atau sebaliknya - Anda ingin mengubah semua panggilan yang tidak ada dalam namespacestd
, namespaceX
, ...), lalu bagaimana Anda mengusulkan untuk melakukan ini?Anda bisa menulis program untuk melakukannya, tetapi bukankah lebih baik menghabiskan waktu mengerjakan proyek Anda sendiri daripada menulis program untuk mempertahankan proyek Anda?
Secara pribadi, saya sebenarnya tidak keberatan
std::
awalannya. Saya suka tampilan lebih daripada tidak memilikinya. Saya tidak tahu apakah itu karena itu eksplisit dan berkata kepada saya "ini bukan kode saya ... Saya menggunakan perpustakaan standar" atau jika itu adalah sesuatu yang lain, tapi saya pikir itu terlihat lebih bagus. Ini mungkin aneh mengingat bahwa saya baru saja masuk ke C ++ (digunakan dan masih melakukan C dan bahasa lainnya lebih lama dan C adalah bahasa favorit saya sepanjang masa, tepat di atas perakitan).Ada satu hal lain meskipun agak terkait dengan hal di atas dan apa yang orang lain tunjukkan. Walaupun ini mungkin praktik yang buruk, saya terkadang memesan
std::name
versi perpustakaan standar dan nama untuk implementasi spesifik-program. Ya, memang ini bisa menggigit Anda dan menggigit Anda dengan keras, tetapi semuanya berakhir saat saya memulai proyek ini dari awal, dan saya satu-satunya programmer untuk itu. Contoh: Saya overloadstd::string
dan menyebutnyastring
. Saya memiliki tambahan yang bermanfaat. Saya melakukannya sebagian karena kecenderungan C dan Unix (+ Linux) saya terhadap nama huruf kecil.Selain itu, Anda dapat memiliki alias namespace. Berikut adalah contoh di mana itu berguna yang mungkin belum dirujuk. Saya menggunakan standar C ++ 11 dan secara khusus dengan libstdc ++. Ya, itu belum lengkap
std::regex
dukungan . Tentu, itu mengkompilasi, tetapi itu membuat pengecualian di sepanjang garis itu menjadi kesalahan pada ujung programmer. Tetapi ini kurang implementasi.Jadi, inilah cara saya menyelesaikannya. Instal Boost's regex, dan tautkan. Kemudian, saya melakukan yang berikut sehingga ketika libstdc ++ telah menerapkannya sepenuhnya, saya hanya perlu menghapus blok ini dan kode tetap sama:
Saya tidak akan berdebat apakah itu ide yang buruk atau tidak. Namun saya akan berpendapat bahwa itu tetap bersih untuk proyek saya dan pada saat yang sama membuatnya lebih spesifik: Benar, saya harus menggunakan Boost, tetapi saya menggunakannya seperti libstdc ++ akhirnya akan memilikinya. Ya, memulai proyek Anda sendiri dan mulai dengan standar (...) di awal berjalan sangat jauh dengan membantu pemeliharaan, pengembangan, dan semua yang terlibat dengan proyek!
Hanya untuk memperjelas sesuatu: Saya sebenarnya tidak berpikir itu ide yang baik untuk menggunakan nama kelas / apa pun di STL dengan sengaja dan lebih khusus di tempat. String adalah pengecualian (abaikan yang pertama, di atas, atau kedua di sini, pun jika Anda harus) untuk saya karena saya tidak suka ide 'String'.
Karena itu, saya masih sangat bias terhadap C dan bias terhadap C ++. Menyimpan detail, banyak dari apa yang saya kerjakan cocok C lebih (tapi itu adalah latihan yang baik dan cara yang baik untuk membuat diri saya a. Belajar bahasa lain dan b. Usahakan jangan kurang bias terhadap objek / kelas / dll yang mungkin lebih baik dinyatakan sebagai kurang berpikiran tertutup, kurang arogan, dan lebih menerima.) Tapi apa yang berguna adalah apa yang sudah disarankan beberapa orang: Saya memang menggunakan daftar (ini cukup generik, bukan?), Dan mengurutkan (hal yang sama) untuk nama dua yang akan menyebabkan bentrokan nama jika saya harus melakukannya
using namespace std;
, dan sebagainya untuk itu saya lebih memilih spesifik, dalam kontrol dan mengetahui bahwa jika saya bermaksud untuk menggunakan standar maka saya harus menentukannya. Sederhananya: asumsi tidak diizinkan.Dan untuk membuat Boost's regex menjadi bagian
std
. Saya melakukan itu untuk integrasi di masa depan dan - sekali lagi, saya akui sepenuhnya ini bias - saya pikir itu tidak seburuk ituboost::regex:: ...
. Memang, itu hal lain bagi saya. Ada banyak hal dalam C ++ yang masih harus saya terima sepenuhnya dalam penampilan dan metode (contoh lain: templat variadic versus argumen var [meskipun saya akui templat variadic sangat berguna!]). Bahkan mereka yang saya terima pun sulit, dan saya masih memiliki masalah dengan mereka.sumber
std
namespace adalah perilaku yang tidak terdefinisi dan karenanya tidak boleh dilakukan.Dari pengalaman saya, jika Anda memiliki banyak perpustakaan yang menggunakan katakanlah
cout
, tetapi untuk tujuan yang berbeda Anda dapat menggunakan yang salahcout
.Misalnya, jika saya mengetik,
using namespace std;
danusing namespace otherlib;
dan mengetik sajacout
(yang kebetulan ada di keduanya), daripadastd::cout
(atau'otherlib::cout'
), Anda mungkin menggunakan yang salah, dan mendapatkan kesalahan. Ini jauh lebih efektif dan efisien untuk digunakanstd::cout
.sumber
Dengan pengidentifikasi impor yang tidak berkualitas, Anda memerlukan alat pencarian eksternal seperti grep untuk mencari tahu di mana pengidentifikasi dinyatakan. Ini membuat alasan tentang kebenaran program lebih sulit.
sumber
Itu tergantung di mana ia berada. Jika itu adalah header umum, maka Anda mengurangi nilai namespace dengan menggabungkannya ke namespace global. Perlu diingat, ini bisa menjadi cara yang rapi untuk membuat modul global.
sumber
Ini adalah praktik buruk, sering dikenal sebagai polusi namespace global. Masalah dapat terjadi ketika lebih dari satu namespace memiliki nama fungsi yang sama dengan tanda tangan, maka akan ambigu bagi kompiler untuk memutuskan mana yang akan dipanggil dan ini semua dapat dihindari ketika Anda menentukan namespace dengan panggilan fungsi Anda seperti
std::cout
. Semoga ini membantu. :)sumber
Untuk menjawab pertanyaan Anda, saya melihatnya dengan cara ini secara praktis: banyak programmer (tidak semua) memanggil namespace std. Karena itu seseorang harus terbiasa TIDAK menggunakan hal-hal yang melanggar atau menggunakan nama yang sama dengan apa yang ada di namespace std. Itu adalah hal yang luar biasa, tetapi tidak terlalu banyak dibandingkan dengan jumlah kata dan nama samaran yang mungkin muncul yang dapat muncul dengan berbicara secara tegas.
Maksud saya benar-benar ... mengatakan "jangan mengandalkan kehadiran ini" hanya membuat Anda bergantung padanya BUKAN hadir. Anda akan selalu mengalami masalah meminjam cuplikan kode dan terus memperbaikinya. Simpan saja barang-barang yang Anda tentukan dan pinjam dalam lingkup terbatas sebagaimana mestinya dan SANGAT hemat dengan global (jujur, global seharusnya hampir selalu menjadi pilihan terakhir untuk tujuan "kompilasi sekarang, kewarasan nanti"). Sungguh saya pikir ini adalah saran buruk dari guru Anda karena menggunakan std akan bekerja untuk "cout" dan "std :: cout" tetapi TIDAK menggunakan std hanya akan bekerja untuk "std :: cout". Anda tidak akan selalu cukup beruntung untuk menulis semua kode Anda sendiri.
CATATAN: Jangan terlalu fokus pada masalah efisiensi sampai Anda benar-benar belajar sedikit tentang cara kerja kompiler. Dengan sedikit pengalaman coding Anda tidak perlu belajar banyak tentang mereka sebelum Anda menyadari betapa mereka mampu menggeneralisasikan kode yang baik menjadi sesuatu yang sederhana. Setiap bit sesederhana jika Anda menulis semuanya dalam C. Kode yang baik hanya serumit yang seharusnya.
sumber
<algorithm>
), tampaknya agak sulit untuk membayangkan bahwa orang yang sama dapat dengan andal menghindari pengidentifikasi tersebut. Lihatlah kode Anda sendiri dan beri tahu saya bahwa Anda tidak pernah memiliki variabel atau fungsi yang dipanggilcount
. Ataudistance
, ataulog
,destroy
,launch
,visit
,beta
,sample
,messages
,clamp
,erase
,copy
,modulus
,left
, dll Belum lagi semua pengenal belum distd
yang akan memecahkan kode Anda ketika C ++ 35 keluar ...