Mengapa "menggunakan namespace std;" dianggap praktik yang buruk?

2640

Saya telah diberitahu oleh orang lain bahwa menulis using namespace std;dalam kode salah, dan bahwa saya harus menggunakan std::coutdan std::cinlangsung 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 stdnamespace)? Apakah itu memengaruhi kinerja?

akbiggs
sumber
512
Jangan lupa Anda bisa melakukan: "using std :: cout;" yang berarti Anda tidak harus mengetik std :: cout, tetapi jangan membawa seluruh namespace std pada saat yang sama.
Bill
2
@a nerd berbayar google-styleguide.googlecode.com/svn/trunk/… tautan tidak berfungsi lagi. Sepertinya tautan baru adalah google.github.io/styleguide/cppguide.html#Other_C++_Features
MCG
64
Sangat buruk untuk menggunakan 'using namespace std' pada ruang lingkup file dalam file header. Menggunakannya dalam file sumber (* .cpp) pada lingkup file setelah semua termasuk tidak begitu buruk, karena efeknya terbatas pada satu unit terjemahan. Bahkan kurang bermasalah menggunakannya di dalam fungsi atau kelas, karena efeknya terbatas pada fungsi atau ruang lingkup kelas.
sh-
5
Saya akan mencegah untuk menggunakan menggunakan direktif tapi untuk ruang nama tertentu seperti std::literals::chrono_literals, Poco::Data:Keywords, Poco::Unitsdan 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.
Ludovic Zenohate Lagouardette
7
@ Jon: Tidak ada hubungannya dengan namespace std pada khususnya. Penekanan saya dimaksudkan pada "pada ruang lingkup file dalam file header". Untuk meletakkannya sebagai saran: Jangan gunakan "menggunakan namespace" (std atau lainnya) pada ruang lingkup file dalam file header. Tidak apa-apa untuk menggunakannya dalam file implementasi. Maaf atas ambiguitasnya.
sh-

Jawaban:

2231

Ini tidak terkait dengan kinerja sama sekali. Tetapi pertimbangkan ini: Anda menggunakan dua perpustakaan yang disebut Foo and Bar:

using namespace foo;
using namespace bar;

Semuanya berfungsi dengan baik, dan Anda dapat menelepon Blah()dari Foo dan Quux()dari Bar tanpa masalah. Tetapi suatu hari Anda meningkatkan ke versi baru Foo 2.0, yang sekarang menawarkan fungsi yang disebut Quux(). Sekarang Anda mengalami konflik: Foo 2.0 dan Bar mengimpor Quux()ke namespace global Anda. Ini akan membutuhkan upaya untuk memperbaikinya, terutama jika parameter fungsi cocok.

Jika Anda telah menggunakan foo::Blah()dan bar::Quux(), maka pengenalan foo::Quux()akan menjadi non-event.

Greg Hewgill
sumber
435
Saya selalu menyukai Python "impor big_honkin_name sebagai bhn" sehingga Anda bisa menggunakan "bhn.something" daripada "big_honkin_name.something" - benar-benar mengurangi pengetikan. Apakah C ++ memiliki sesuatu seperti itu?
paxdiablo
764
@Pax namespace io = boost :: filesystem;
AraK
152
Saya pikir itu melebih-lebihkan hal untuk mengatakan itu "beberapa upaya untuk memperbaiki". Anda tidak akan memiliki instance foo :: Quux yang baru, jadi cukup abaikan semua penggunaan Anda saat ini dengan bar :: Quux.
MattyT
289
Apakah orang yang masuk akal akan membuat perpustakaan dengan tipe yang namanya tidak memenuhi syarat bertabrakan dengan tipe std?
erikkallen
94
@ Tom: Masalahnya #defineadalah tidak membatasi dirinya sendiri pada ruang nama, tetapi menginjak seluruh basis kode. Alias ​​namespace adalah yang Anda inginkan.
sbi
1391

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 Anda Quux()daripada bar::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 stdnamespace memiliki ton pengidentifikasi, banyak yang sangat yang umum (berpikir list, 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 bahwa usingarahan 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) usingsebenarnya 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 menemukan std::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.

sbi
sumber
140
Itu secara signifikan merusak kepadatan kode yang dapat Anda bungkus dalam satu baris. Anda akhirnya menulis kode Anda dengan cara yang sangat bertele-tele; yang mengurangi keterbacaan. Secara pribadi, saya pikir kode yang lebih pendek (tapi tidak terlalu pendek) cenderung lebih mudah dibaca (karena ada lebih sedikit barang untuk dibaca, dan lebih sedikit barang untuk terganggu).
Lie Ryan
92
Kira Anda ketinggalan pada hari-hari sebelumnya sebelum C ++ memiliki stringkelas standar , dan tampaknya setiap perpustakaan memiliki sendiri. Memberitahu Anda: Kami akan terus menulis kode kami std::, dan Anda dapat menjalankan kode kami grep -v std:: | vimsaat menjelajahinya. Atau Anda dapat mengajarkan editor Anda bahwa std::kata kunci yang akan diwarnai sama dengan warna latar belakang. Apapun yang berhasil.
Mike DeSimone
80
Saya pikir tidak 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 dalam stdnamespace, dan kemudian usingpernyataan dalam lingkup tertentu memecahkan masalah dengan baik. Namun dalam kasus umum, ini bukan noise, ia menyampaikan informasi berharga selain menghilangkan ambiguitas
jalf
147
Setiap kali saya melihat std::, saya tahu itu akan menjadi dari std::tanpa harus memikirkannya. Jika saya melihat stringatau listatau mapsendiri, aku bertanya-tanya sedikit.
Mateen Ulhaq
68
@ LieRyan Maka semoga berhasil menulis perpustakaan geometri tanpa pernah menyebut nama vector, transformatau distance. 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.
Christian Rau
420

Masalah dengan menempatkan using namespacefile 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 usingpernyataan 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,

Arahan penggunaan ada untuk kode C ++ lama dan untuk memudahkan transisi ke namespace, tetapi Anda mungkin tidak boleh menggunakannya secara teratur, setidaknya tidak dalam kode C ++ baru Anda.

FAQ menyarankan dua alternatif:

  • Deklarasi menggunakan:

    using std::cout; // a using-declaration lets you use cout without qualification
    cout << "Values:";
  • Cukup ketikkan std ::

    std::cout << "Values:";
ChrisW
sumber
1
Tentu saja Anda tidak boleh menganggap status global cout juga, jangan sampai seseorang memiliki std: cout << std :: hex dan gagal std :: restore_cout_state sesudahnya. Tapi itu adalah fatberg lainnya.
Móż
233

Saya baru-baru ini mendapat keluhan tentang Visual Studio 2010 . Ternyata hampir semua file sumber memiliki dua baris ini:

using namespace std;
using namespace boost;

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.

David Thornley
sumber
14
Ini. Boost dan std memiliki banyak tumpang tindih - terutama sejak C ++ 11.
einpoklum
1
Saya melakukannya sekali dan belajar pelajaran dengan cara yang sulit. Sekarang saya tidak pernah menggunakan usingdefinisi fungsi di luar dan jarang menggunakan using namespacesama sekali.
Ferruccio
210

Versi singkat: jangan gunakan usingdeklarasi 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):

Ringkasan

Penggunaan namespace adalah untuk kenyamanan Anda, bukan untuk Anda berikan kepada orang lain: Jangan pernah menulis deklarasi penggunaan atau arahan penggunaan sebelum arahan #include.

Akibat wajar: Dalam file header, jangan menulis level namespace menggunakan arahan atau menggunakan deklarasi; sebagai gantinya, secara eksplisit namespace-kualifikasi semua nama. (Aturan kedua mengikuti dari yang pertama, karena tajuk tidak akan pernah tahu apa yang mungkin muncul # tajuk lainnya setelah mereka.)

Diskusi

Singkatnya: Anda dapat dan harus menggunakan namespace menggunakan deklarasi dan arahan secara bebas dalam file implementasi Anda setelah #sertakan arahan dan merasa senang tentang hal itu. Meskipun pernyataan berulang yang bertentangan, namespace menggunakan deklarasi dan arahan tidak jahat dan mereka tidak mengalahkan tujuan ruang nama. Sebaliknya, mereka adalah apa yang membuat ruang nama dapat digunakan .

mattnewport
sumber
4
Hanya satu pendapat programmer lagi di sini, tetapi sementara saya setuju 100% dengan pernyataan bahwa kata itu usingseharusnya tidak pernah muncul di header, saya tidak yakin tentang lisensi gratis untuk menempatkan using namespace xyz;di mana saja dalam kode Anda, terutama jika xyzitu std. Saya menggunakan using 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.
dgnuff
2
@Lightness Races di Orbit tentu saja Anda berhak atas pendapat Anda. Akan lebih membantu jika ada upaya penjelasan mengapa Anda tidak setuju dengan saran yang diberikan dalam jawaban ini. Terutama akan menarik untuk memahami apa gunanya ruang nama jika 'menggunakan' itu buruk? Mengapa tidak hanya menamai benda std_cout alih-alih std :: cout ... pembuat C ++ / namespace pasti memiliki ide ketika mereka repot-repot membuatnya.
nyholku
1
@nyholku: Tidak perlu - mayoritas jawaban lain memberikan alasan yang sama dengan saya. Juga tolong jangan ragu untuk mencatat ":)" Saya menambahkan komentar saya! Dan saya tidak mengatakan ruang nama itu buruk.
Lightness Races in Orbit
Ya, saya perhatikan itu :) tetapi IMO sebagian besar jawaban (yang bertentangan dengan saran bijak ini) salah arah (bukan saya membuat statistik apa pun yang mayoritas sekarang). Jika Anda setuju bahwa namespace 'tidak buruk' maka Anda mungkin mengatakan di mana Anda pikir itu sesuai jika Anda tidak setuju dengan jawaban ini?
nyholku
Saya tidak bisa menahan perasaan bahwa using namespaceitu jahat, seperti gotokejahatan. Keduanya memiliki kegunaan yang valid, tetapi 999 kali dari 1000 mereka akan digunakan salah. Jadi, ya, dengan using namespacedi sumber Anda tidak akan mencemari namespace termasuk lainnya, rapi. Tapi itu masih tidak akan melindungi Anda dari "kesenangan" yang muncul dari using namespace Foo+ using namespace Bardengan Anda menelepon (implisit Foo: :) baz(xyz)dan tiba-tiba pemecah kode (tanpa perubahan terkait) hanya karena Bar::baz()ditambahkan di suatu tempat, yang kebetulan menjadi lebih baik cocok (dan dengan demikian sekarang dipanggil sebagai gantinya)
CharonX
122

Seseorang seharusnya tidak menggunakan usingarahan di lingkup global, terutama di header. Namun, ada situasi di mana itu sesuai bahkan dalam file header:

template <typename FloatType> inline
FloatType compute_something(FloatType x)
{
    using namespace std; // No problem since scope is limited
    return exp(x) * (sin(x) - cos(x * 2) + sin(x * 3) - cos(x * 4));
}

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)).

robson3.14
sumber
9
Maaf, tapi saya sangat tidak setuju dengan ini.
Billy ONeal
4
@Illy: Tidak ada cara lain untuk mendukung pemanggilan userlib :: cos (userlib :: superint). Setiap fitur memiliki kegunaan.
Zan Lynx
17
@ Zan: Tentu saja ada. using std::cos;,, using std::sindll. Masalahnya adalah bahwa semua yang dirancang dengan baik userlibakan memiliki sindan cosdi dalam ruang nama mereka sendiri juga, jadi ini benar-benar tidak membantu Anda. (Kecuali ada using namespace userlibsebelum template ini dan itu sama buruknya using namespace std- dan ruang lingkup di sana tidak terbatas.) Selain itu, satu-satunya fungsi seperti ini yang pernah saya lihat terjadi adalah swap, dan dalam kasus seperti itu saya akan merekomendasikan hanya membuat template spesialisasi std::swapdan menghindari seluruh masalah.
Billy ONeal
11
@BillyONeal: 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.
sbi
38
@BillyONeal: Komentar (7-kali-tervotasikan!) Anda salah - situasi yang Anda uraikan persis seperti apa yang dirancang ADL untuk dibahas. Secara singkat, jika xmemiliki satu atau lebih "ruang nama terkait" (misalnya jika itu didefinisikan dalam namespace userlib) maka setiap fungsi panggilan yang terlihat seperti cos(x)akan juga terlihat pada mereka ruang nama - tanpa apa pun using namespace userlib;terlebih dahulu menjadi diperlukan. Zan Lynx benar (dan pencarian nama C ++ adalah byzantine ...)
j_random_hacker
97

Jangan menggunakannya secara global

Itu dianggap "buruk" hanya jika digunakan secara global . Karena:

  • Anda mengacaukan namespace tempat Anda pemrograman.
  • Pembaca akan mengalami kesulitan melihat dari mana pengenal tertentu berasal, ketika Anda menggunakan banyak using namespace xyz.
  • Apa pun yang benar bagi pembaca lain dari kode sumber Anda bahkan lebih benar bagi pembaca yang paling sering: kode sendiri. Kembalilah dalam satu atau dua tahun dan lihatlah ...
  • Jika Anda hanya berbicara tentang using namespace stdAnda mungkin tidak menyadari semua hal yang Anda ambil - dan ketika Anda menambahkan yang lain #includeatau 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 swapfungsi untuk kelas Anda. Disarankan agar Anda benar-benar menggunakan lokal using namespace std- atau setidaknya using std::swap:

class Thing {
    int    value_;
    Child  child_;
public:
    // ...
    friend void swap(Thing &a, Thing &b);
};
void swap(Thing &a, Thing &b) {
    using namespace std;      // make `std::swap` available
    // swap all members
    swap(a.value_, b.value_); // `std::stwap(int, int)`
    swap(a.child_, b.child_); // `swap(Child&,Child&)` or `std::swap(...)`
}

Ini melakukan keajaiban berikut:

  • Compiler akan memilih std::swapuntuk value_, yaitu void std::swap(int, int).
  • Jika Anda memiliki kelebihan beban void swap(Child&, Child&), kompiler akan memilihnya.
  • Jika Anda tidak memiliki kelebihan itu, kompiler akan menggunakan 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::swaptelah diubah untuk menemukan potensi kelebihan dan memilihnya.

towi
sumber
5
"Implementasi std :: swap telah diubah untuk menemukan potensi kelebihan dan memilihnya." - Apa? Apa kamu yakin akan hal itu? Meskipun memang benar bahwa memberikan kebiasaan swapdi tempat pertama tidak begitu penting di C ++ 11 lagi, karena std::swapitu sendiri lebih fleksibel (menggunakan semantik bergerak). Tapi std::swapsecara otomatis memilih swap kustom Anda sendiri, itu benar-benar baru bagi saya (dan saya tidak benar-benar percaya).
Christian Rau
@ChristianRau saya pikir begitu, ya. Saya membaca ini di SO di suatu tempat. Kita selalu bisa bertanya kepada Howard , dia harus tahu. Saya menggali dan menggali sekarang ...
towi
14
Bahkan dalam kasus swap, idiom yang lebih jelas (dan untungnya lebih umum) adalah menulis using std::swap;daripada using namespace std;. Idiom yang lebih spesifik memiliki lebih sedikit efek samping dan karenanya membuat kode lebih dapat dipertahankan.
Adrian McCarthy
11
Kalimat terakhir salah. Dalam C ++ 11 Std Swap Two Step secara resmi diberkati sebagai cara yang tepat untuk menelepon swap, dan berbagai tempat lain dalam standar diubah untuk mengatakan mereka memanggil swapseperti itu (NB seperti yang dinyatakan di atas, using std::swapadalah cara yang benar, bukan using namespace std). Tapi std::swapitu dengan tegas tidak diubah untuk menemukan yang lain swapdan menggunakannya. Jika std::swapdipanggil, maka std::swapterbiasa.
Jonathan Wakely
3
Mungkin lebih bijaksana untuk mengetik saja using std::swapsecara 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.
Lundin
79

Jika Anda mengimpor file header yang tepat Anda tiba-tiba memiliki nama seperti hex, left, plusatau countdalam lingkup global Anda. Ini mungkin mengejutkan jika Anda tidak sadar yang std::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.

sth
sumber
12
+1 belum lagi 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.
Ceria dan hth. - Alf
Agar adil, Anda tidak memiliki sebagian besar dari itu jika Anda tidak memasukkannya <iomanip>. Tetap saja, poin bagus.
einpoklum
48

Alasan lainnya adalah kejutan.

Jika saya melihat cout << blah, alih-alih std::cout << blahsaya berpikir: Apa ini cout? Apakah ini normal cout? Apakah ini sesuatu yang istimewa?

Martin Beckett
sumber
25
Apakah ini lelucon? Aku benar-benar tidak tahu. Jika tidak maka saya pribadi akan menganggap itu adalah 'cout' yang normal kecuali Anda tidak mempercayai kode tersebut karena jika tidak maka akan menjadi bau kode BEYOND MAJOR, IMO. ... Dan jika Anda tidak mempercayai kodenya maka mengapa Anda menggunakannya? Perhatikan bahwa saya tidak mengatakan "TRUST EVERYThING !!" tetapi ini juga agak jauh dibuat jika Anda, katakanlah, berurusan dengan beberapa perpustakaan terkenal dari GitHub atau sesuatu.
Brent Rittenhouse
28
@BrentRittenhouse coutadalah contoh buruk karena semua orang mengenalinya. Tapi bayangkan futuredi aplikasi keuangan. Apakah itu kontrak untuk membeli atau menjual sesuatu pada tanggal yang ditentukan? Bukan itu. Jika kode mengatakan std::futureAnda tidak akan mudah bingung.
James Hollis
2
@BrentRittenhouse mungkin contoh yang sedikit buruk, setidaknya ada empat perpustakaan berbeda yang memiliki cout. Mungkin "apakah itu perpustakaan standar? Libstdc ++? Stl? Sesuatu yang lain?" Dan tidak, tidak semua orang tahu std :: cout, setidaknya secara inheren, 6 dari 7 pekerja baru yang kami terima tidak. Karena kurikulum pendidikan tidak menggunakan mereka dalam pendidikan. Saya harus mengusir printfs. Atau debug () - dari Qt.
Swift - Friday Pie
1
Betulkah? Ini cukup banyak dalam contoh pertama dari bab pertama dari sooo banyak buku tentang C ++, jika ada itu (dengan penggunaan operator penyisipan) adalah satu - satunya C ++ beberapa badan baru yang tahu.
mckenzm
@ mckenzm Saya mungkin memasukkannya ke dalam buku atau catatan kuliah untuk mengurangi kekacauan, tetapi tidak dalam kode
Martin Beckett
45

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:

  1. Function-level using-directives dan using-declarations di dalam implementasi fungsi
  2. Sumber-file-level menggunakan deklarasi di dalam file sumber
  3. (Kadang-kadang) arahan tingkat file sumber
Alexander Poluektov
sumber
43

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 ++" :

namespace My_lib {

    using namespace His_lib; // Everything from His_lib
    using namespace Her_lib; // Everything from Her_lib

    using His_lib::String; // Resolve potential clash in favor of His_lib
    using Her_lib::Vector; // Resolve potential clash in favor of Her_lib

}

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).

Oleksiy
sumber
29

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 sungai coutatau cin. ;)

Yelonek
sumber
7
Itu deklarasi menggunakan lokal , hal yang sangat berbeda dari menggunakan direktif .
sbi
25

Sangat menyenangkan melihat kode dan tahu apa fungsinya. Jika saya melihat std::coutsaya tahu itu coutaliran stdperpustakaan. Jika saya melihat coutmaka saya tidak tahu. Itu bisa menjadi coutaliran stdperpustakaan. Atau mungkin ada int cout = 0;sepuluh baris yang lebih tinggi dalam fungsi yang sama. Atau staticvariabel bernama coutdalam 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 membaca static intnama cout, 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.

gnasher729
sumber
4
Bagaimana Anda tahu "std :: cout << 1" tidak membaca cout statis bernama int di namespace std menggesernya dengan satu dan membuang hasil? Juga bagaimana Anda tahu apa yang "<<" lakukan;) ??? ... sepertinya jawaban ini bukan titik data yang baik untuk menghindari 'menggunakan'.
nyholku
4
Jika seseorang telah mendefinisikan ulang std :: cout menjadi bilangan bulat, maka masalah Anda bukan teknis, tetapi sosial - seseorang memilikinya untuk Anda. (dan Anda mungkin juga harus memeriksa semua tajuk untuk hal-hal seperti #define true false, dll)
Jeremy Friesner
2
Ketika saya melihat cout, saya tahu itu std :: cout, selalu. Jika saya salah, itu masalah orang yang menulis kode ini, bukan saya :)
Tien Do
22

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.

Praha Sangha
sumber
18

Mempertimbangkan

// myHeader.h
#include <sstream>
using namespace std;


// someoneElses.cpp/h
#include "myHeader.h"

class stringstream {  // Uh oh
};

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.

Ron Warholic
sumber
18
  1. Anda harus dapat membaca kode yang ditulis oleh orang-orang yang memiliki gaya dan pendapat praktik terbaik yang berbeda dari Anda.

  2. 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".

Dustin Getz
sumber
17

Menggunakan banyak namespace pada saat yang sama jelas merupakan resep untuk bencana, tetapi menggunakan JUST namespace stddan 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.

pengguna2645752
sumber
Membuat tabrakan tidak sulit - string pendek seperti min, enddan lessmuncul di std::namespace. Tetapi lebih dari itu, sekarang yang std::memiliki ribuan simbol di dalamnya, berguna bagi pembaca untuk mengetahui dari mana simbol baru yang mungkin tidak mereka ketahui berasal.
Tom Swirly
Std namespace ada karena orang, baik Anda, kolega Anda, atau orang yang menulis middleware yang Anda gunakan, tidak selalu bijak dalam menempatkan fungsi di dalam ruang nama. Dengan demikian Anda dapat mengimpor semua std :: dan tidak ada yang lain, sambil tetap memunculkan tabrakan antara, katakanlah, std :: min dan warisan orang lain :: min () dari sebelum waktu ketika std.
Aiken Drum
14

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.

// Header
class File
{
   typedef std::vector<std::string> Lines;
   Lines ReadLines();
}

dan dalam implementasinya:

// .cpp
Lines File::ReadLines()
{
    Lines lines;
    // Get them...
    return lines;
}

sebagai lawan:

// .cpp
vector<string> File::ReadLines()
{
    vector<string> lines;
    // Get them...
    return lines;
}

atau:

// .cpp
std::vector<std::string> File::ReadLines()
{
    std::vector<std::string> lines;
    // Get them...
    return lines;
}
Carl
sumber
Hanya komentar kecil, sementara typedef berguna, saya akan mempertimbangkan membuat kelas yang mewakili Lines daripada menggunakan typedef.
Eyal Solnik
14

Contoh nyata untuk mengklarifikasi masalah tersebut. Bayangkan Anda memiliki situasi di mana Anda memiliki dua perpustakaan, foodan barmasing-masing memiliki ruang nama sendiri:

namespace foo {
    void a(float) { /* Does something */ }
}

namespace bar {
    ...
}

Sekarang katakanlah Anda menggunakan foodan barbersama - sama dalam program Anda sendiri sebagai berikut:

using namespace foo;
using namespace bar;

void main() {
    a(42);
}

Pada titik ini semuanya baik-baik saja. Ketika Anda menjalankan program Anda, itu 'Melakukan sesuatu'. Tetapi kemudian Anda memperbarui bardan katakanlah itu telah berubah menjadi seperti:

namespace bar {
    void a(float) { /* Does something completely different */ }
}

Pada titik ini Anda akan mendapatkan kesalahan kompilator:

using namespace foo;
using namespace bar;

void main() {
    a(42);  // error: call to 'a' is ambiguous, should be foo::a(42)
}

Jadi, Anda perlu melakukan pemeliharaan untuk mengklarifikasi maksud 'a' foo::a. Itu tidak diinginkan, tapi untungnya itu cukup mudah (cukup tambahkan foo::di depan semua panggilana yang kompiler menandai sebagai ambigu).

Tapi bayangkan skenario alternatif di mana bilah berubah sebagai gantinya:

namespace bar {
    void a(int) { /* Does something completely different */ }
}

Pada titik ini panggilan Anda untuk a(42)tiba - tiba mengikat, bar::abukan 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 namespacestd (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.

Kevin
sumber
Skenario kedua meraih kesepakatan untuk saya. Tidak ada ruang nama lagi. Tidak dapat memiliki perubahan halus dalam fungsi yang tidak terdeteksi di bawah tenda.
safe_malloc
13

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:

namespace Mylib{
    template<class T> class Stack{ /* ... */ };
    // ...
}

namespace Yourlib{
    class Stack{ /* ... */ };
    // ...
}

void f(int max) {
    Mylib::Stack<int> s1(max); // Use my stack
    Yourlib::Stack    s2(max); // Use your stack
    // ...
}

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:

void f(int max) {
    using namespace Mylib; // Make names from Mylib accessible
    Stack<int> s1(max); // Use my stack
    Yourlib::Stack s2(max); // Use your stack
    // ...
}

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

Rohan Singh
sumber
4
Sangat menarik bahwa jawaban ini yang didasarkan pada bimbingan dari yang lain bahwa Bjarne Stroustrup telah mendapatkan -2 ... anak laki-laki Bjarne pasti seorang programmer yang miskin dan tidak berpengalaman ketika ia memperkenalkan fitur ini ke dalam C ++
nyholku
@nyholku: Lihat ini .
sbi
10

Contoh di mana using namespace stdmelempar kesalahan kompilasi karena ambiguitas jumlah, yang juga merupakan fungsi dalam pustaka algoritma.

#include <iostream>

using namespace std;

int count = 1;
int main() {
    cout << count << endl;
}
Nithin
sumber
2
::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.
PSkocik
Masalah sebenarnya di sini adalah bahwa C ++ masih memiliki global namespace-less. Ini, dan fakta bahwa 'ini' tersirat dalam metode, menyebabkan begitu banyak bug dan masalah yang saya bahkan tidak bisa menghitungnya, bahkan dengan variabel 'hitungan' yang tepat. ;)
Aiken Drum
9

Itu tidak membuat kinerja perangkat lunak atau proyek Anda lebih buruk. Dimasukkannya namespace di awal kode sumber Anda tidak buruk. Dimasukkannya using namespace stdinstruksi bervariasi sesuai dengan kebutuhan Anda dan cara Anda mengembangkan perangkat lunak atau proyek.

The namespace stdberisi fungsi standar C ++ dan variabel. Namespace ini berguna ketika Anda sering menggunakan fungsi standar C ++.

Seperti yang disebutkan di halaman ini :

Pernyataan yang menggunakan namespace std umumnya dianggap praktik buruk. Alternatif untuk pernyataan ini adalah untuk menentukan namespace yang dimiliki oleh pengidentifikasi menggunakan operator lingkup (: :) setiap kali kita mendeklarasikan suatu tipe.

Dan lihat pendapat ini :

Tidak ada masalah menggunakan "menggunakan namespace std" di file sumber Anda ketika Anda menggunakan namespace dan tahu pasti bahwa tidak ada yang akan bertabrakan.

Beberapa orang mengatakan itu adalah praktik buruk untuk memasukkan using namespace stddalam 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 dalam namespace stdAnda akan membebani fungsi dan itu bisa menghasilkan masalah karena mengkompilasi atau mengeksekusi. Itu tidak akan dikompilasi atau dieksekusi seperti yang Anda harapkan.

Seperti yang disebutkan di halaman ini :

Meskipun pernyataan itu menyelamatkan kita dari pengetikan std :: kapan pun kita ingin mengakses kelas atau tipe yang didefinisikan dalam std namespace, ia mengimpor keseluruhan std namespace ke dalam namespace program saat ini. Mari kita ambil beberapa contoh untuk memahami mengapa ini mungkin bukan hal yang baik

...

Sekarang pada tahap pengembangan selanjutnya, kami ingin menggunakan versi cout lain yang diterapkan secara khusus di beberapa pustaka yang disebut "foo" (misalnya)

...

Perhatikan bagaimana ada ambiguitas, ke perpustakaan mana cout menunjuk? Kompiler dapat mendeteksi ini dan tidak mengkompilasi program. Dalam kasus terburuk, program mungkin masih mengkompilasi tetapi memanggil fungsi yang salah, karena kami tidak pernah menentukan ke namespace mana pengenal itu berada.

CryogenicNeo
sumber
7

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.

Watson
sumber
7

"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?

Solkar
sumber
19
Ini bukan hanya 5 karakter tambahan; 5 karakter tambahannya setiap kali Anda mereferensikan tipe objek apa pun di pustaka standar. Yang, jika Anda menggunakan perpustakaan standar sangat banyak, akan sering. Jadi, lebih realistis, ribuan karakter tambahan dalam program berukuran layak. Agaknya arahan 'menggunakan' ditambahkan ke bahasa sehingga dapat digunakan ...
Jeremy Friesner
5
Ini bukan 5 karakter tambahan setiap kali, ini 5 karakter dan mungkin beberapa klik mouse untuk menarik turun menu dan melakukan Temukan dan Ganti di editor pilihan Anda.
DaveWalley
1
Keterbacaan. cout << hex << setw(4) << i << endl;lebih mudah dibaca daripadastd::cout << std::hex << std::setw(4) << i << std::endl;
oz1cz
16
Dan yang lebih buruk: std::map<std::string,std::pair<std::string,std::string>>mengerikan dibandingkan dengan map<string,pair<string,string>>.
oz1cz
4
Ini praktik yang baik adalah mengetikkan kontainer STL Anda, jadi std :: benar-benar tidak masalah. Dan C ++ 11 memberi kita kata kunci otomatis yang membuat segalanya menjadi lebih mudah ketika misalnya menggunakan iterator.
juzzlin
7

Saya setuju dengan orang lain - itu meminta bentrokan nama, ambiguitas dan kemudian faktanya kurang eksplisit. Sementara saya bisa melihat penggunaanusing , 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 stdnamespace (atau sebaliknya - Anda ingin mengubah semua panggilan yang tidak ada dalam namespace std, namespace X, ...), 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::nameversi 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 menyebutnya string. 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 lengkapstd::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:

namespace std
{
    using boost::regex;
    using boost::regex_error;
    using boost::regex_replace;
    using boost::regex_search;
    using boost::regex_match;
    using boost::smatch;
    namespace regex_constants = boost::regex_constants;
}

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 itu boost::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.

Peter Mortensen
sumber
1
Memperluas stdnamespace adalah perilaku yang tidak terdefinisi dan karenanya tidak boleh dilakukan.
tambre
7

Dari pengalaman saya, jika Anda memiliki banyak perpustakaan yang menggunakan katakanlah cout, tetapi untuk tujuan yang berbeda Anda dapat menggunakan yang salah cout.

Misalnya, jika saya mengetik, using namespace std;dan using namespace otherlib;dan mengetik saja cout(yang kebetulan ada di keduanya), daripada std::cout(atau 'otherlib::cout'), Anda mungkin menggunakan yang salah, dan mendapatkan kesalahan. Ini jauh lebih efektif dan efisien untuk digunakan std::cout.

Engine Dev
sumber
6

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.

August Karlstrom
sumber
6

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.

MathGladiator
sumber
6

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. :)

dan.911
sumber
5

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.

Noneyo Getit
sumber
Mengingat berapa banyak orang yang tampaknya tidak menyadari fungsi perpustakaan standar yang berguna (misalnya, menciptakan kembali hal-hal dari <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 dipanggil count. Atau distance, atau log, destroy, launch, visit, beta, sample, messages, clamp, erase, copy, modulus, left, dll Belum lagi semua pengenal belum di stdyang akan memecahkan kode Anda ketika C ++ 35 keluar ...
Toby Speight