Menggunakan std Namespace

110

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?

paoloricardo
sumber

Jawaban:

131

Sebagian besar pengguna C ++ cukup senang membaca std::string, std::vectordll. Faktanya, melihat mentah vectormembuat saya bertanya-tanya apakah ini adalah std::vectordefinisi pengguna atau yang berbeda vector.

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 stdnamespace: count, sort, find, equal, reverse. Memiliki variabel yang disebut lokal countberarti bahwa using namespace stdtidak akan memungkinkan Anda untuk menggunakan countbukan std::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.

#include <algorithm>
using namespace std;

int count = 0;

int increment()
{
    return ++count; // error, identifier count is ambiguous
}

Kesalahan biasanya panjang dan tidak bersahabat karena std::countmerupakan template dengan beberapa tipe bersarang yang panjang.

Ini tidak masalah, karena std::countmasuk ke namespace global dan jumlah fungsi menyembunyikannya.

#include <algorithm>
using namespace std;

int increment()
{
    static int count = 0;
    return ++count;
}

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::countterlihat seperti countpada namespace global, tetapi hanya di dalam increment.

#include <algorithm>

int increment()
{
    using namespace std;
    static int count = 0;
    return ++count;
}

Dan untuk alasan serupa, countambigu di sini. using namespace stdtidak menyebabkan std::count, sembunyikan bagian luar countseperti yang diharapkan. The using namespaceAturan berarti bahwa std::countpenampilan (dalam incrementfungsi) seolah-olah itu dideklarasikan di lingkup global, yaitu pada ruang lingkup yang sama seperti int count = 0;dan karenanya menyebabkan ambiguitas.

#include <algorithm>

int count = 0;

int increment()
{
    using namespace std;
    return ++count; // error ambiguous
}
CB Bailey
sumber
21
tetapi jenis soooo jauh lebih mudah tanpa std :: awalan!
xtofl
69
@xtofl: Tidak, tidak. Lima karakter tidak terlalu relevan saat mengetik, tetapi lima karakter ini mungkin sangat relevan saat membaca. Dan kemudahan membaca lebih penting daripada kemudahan mengetik untuk kode sumber, karena kode lebih banyak dibaca daripada ditulis.
sbi
3
Anda dapat menambahkan bahwa pernyataan using berperilaku dengan benar dengan aturan lingkup.
Martin York
2
@ Martin York: Diperbarui dengan contoh yang menggambarkan aturan pelingkupan. @Michael Burr: Bisa dibilang itu tidak terlalu buruk, yang sebenarnya tidak saya sukai adalah di mana pesan kesalahan untuk kesalahan sederhana menjadi jauh lebih sulit untuk ditafsirkan, atau di mana itu tidak terjadi sama sekali. Misalnya, jika suatu fungsi diyakini berada dalam cakupan, tetapi tidak dan std :: function adalah, daripada mendapatkan kesalahan 'pengenal tidak dikenali' yang membantu, Anda sering berakhir dengan argumen yang lebih tidak jelas 'tidak dapat mengonversi Kesalahan gaya X 'atau' tidak dapat menghasilkan fungsi dari template '. Lebih buruk lagi jika fungsi yang salah dipanggil secara diam-diam. Ini jarang terjadi, tetapi terjadi.
CB Bailey
5
Nah, heran tidak ada yang membahas tentang opsi using std::xxx;. Itu tidak menyebabkan polusi namespace, menulis kode akan lebih pendek dan saya pikir copylebih banyak dibaca daripada std::copy.
legends2k
41

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

using namespace std

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

using std::swap

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

Yacoby
sumber
10
1 untuk disebutkan using std::swap(yang merupakan satu-satunya hal yang pernah saya gunakan).
sbi
1
1 untuk menyebutkan yang u n sdapat menyebar. Hanya untuk dicatat bahwa itu juga bisa masuk ke dalam header yang dibangun dengan benar: Mereka hanya harus dimasukkan setelah header nakal.
quamrana
1
Tetapi jika Anda menentukan spesialisasi swapatau move(atau hash, lessdll.), Anda harus memasukkan spesialisasi itu ke namespace stddalamnya. 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&)};
AJMansfield
28

Pertama, beberapa terminologi:

  • menggunakan-deklarasi : using std::vector;
  • menggunakan-direktif : using namespace std;

Saya pikir menggunakan direktif penggunaan baik-baik saja, selama mereka tidak digunakan pada lingkup global di file header. Jadi memiliki

using namespace std;

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 dari stdnamespace 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 stdnamespace, 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):

template< typename T >
void foo( T& x, T& y)
{
    using std::swap;     // makes std::swap available in this function

    // do stuff...

    swap( x, y);         // will use a T-specific swap() if it exists,
                         //  otherwise will use std::swap<T>()

    // ...
 }

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:

Singkatnya: Anda dapat dan harus menggunakan namespace menggunakan deklarasi dan arahan secara bebas dalam file implementasi Anda setelah #includearahan dan merasa nyaman karenanya. Meskipun pernyataan berulang yang bertentangan, namespace yang menggunakan deklarasi dan arahan tidak jahat dan tidak mengalahkan tujuan namespace. Sebaliknya, itulah yang membuat namespace dapat digunakan.

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:

Sebuah menggunakan-deklarasi menambahkan nama untuk lingkup lokal. A using-directive tidak; itu hanya membuat nama dapat diakses dalam cakupan di mana mereka dideklarasikan. Sebagai contoh:

namespaceX {
    int i , j , k ;
}

int k ;
void f1()
{
    int i = 0 ;

    using namespaceX ; // make names from X accessible

    i++; // local i
    j++; // X::j
    k++; // error: X::k or global k ?

    ::k ++; // the global k

    X::k ++; // X’s k
}

void f2()
{
    int i = 0 ;

    using X::i ; // error: i declared twice in f2()
    using X::j ;
    using X::k ; // hides global k

    i++;
    j++; // X::j
    k++; // X::k
}

Nama yang dideklarasikan secara lokal (dideklarasikan dengan deklarasi biasa atau dengan deklarasi menggunakan) menyembunyikan deklarasi nonlokal dengan nama yang sama, dan setiap overloading ilegal dari nama tersebut terdeteksi pada titik deklarasi.

Perhatikan kesalahan ambiguitas untuk k++dalam f1(). Nama global tidak lebih diutamakan daripada nama dari namespace yang dapat diakses dalam lingkup global. Hal ini memberikan perlindungan yang signifikan terhadap benturan nama yang tidak disengaja, dan - yang terpenting - memastikan bahwa tidak ada keuntungan yang bisa diperoleh dari pencemaran namespace global.

Saat library yang mendeklarasikan banyak nama dibuat dapat diakses melalui using-directives, ada keuntungan signifikan bahwa benturan nama yang tidak digunakan tidak dianggap sebagai error.

...

Saya berharap melihat penurunan drastis dalam penggunaan nama global dalam program baru yang menggunakan ruang nama dibandingkan dengan program C dan C ++ tradisional. Aturan untuk namespace secara khusus dibuat untuk tidak memberikan keuntungan bagi pengguna nama global yang '' malas '' dibandingkan seseorang yang berhati-hati untuk tidak mencemari cakupan global.

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

Michael Burr
sumber
Sehubungan dengan poin terakhir Anda: Java dan C # juga memiliki namespace yang jauh lebih rapi. Jika semua yang ada di BCL tinggal di Sistem, "menggunakan Sistem" akan menyebabkan masalah yang sama banyaknya dengan "menggunakan namespace std".
Jeff Hardy
Tetapi program Java dan C # yang saya lihat biasanya membawa semua namespace yang mereka gunakan - bukan hanya "Sistem" (atau yang setara). Jadi, alih-alih menggunakan satu direktif yang membawa semua nama yang digunakan, ada 5 atau 10 yang melakukan hal yang kurang lebih sama. Juga, apakah "menggunakan namespace std;" benar-benar menyebabkan banyak masalah?
Michael Burr
Masalahnya adalah std memiliki terlalu banyak nama umum dan termasuk satu tajuk standar dapat mencakup semua yang lain. Kami tidak memiliki kontrol yang baik atas apa yang diimpor, risikonya terlalu banyak. Saya tidak cukup tahu tentang Java dan C #, tetapi saya tahu tentang Ada yang memiliki sistem modul yang jauh lebih baik daripada C ++ dan di mana mengimpor nama biasanya tidak disukai. Secara umum, yang pertama adalah masalah konvensi penamaan (saya telah melihat orang menggunakan awalan serta namespace, tidak mengimpor tidak masuk akal) lalu gaya.
Pemrogram
1
Saya masih belum yakin bahwa ini adalah masalah dunia nyata. Saya melihat penggunaan arahan digunakan sepanjang waktu tanpa kekurangan yang parah. Kemudian lagi, saya tidak punya masalah dengan tidak menggunakannya. Saya hanya lebih suka bahwa std::kualifikasi tidak mengacaukan kode - ada cara lain untuk menghindarinya (menggunakan-deklarasi atau typedef biasanya melakukan triknya).
Michael Burr
1
@Programmer: Anda mengatakan, "daftar adalah pengenal alami untuk mengidentifikasi daftar di penerjemah cadel" - tetapi memiliki " using namespace std;" direktif tidak mencegah Anda untuk menyatakan pengenal alami Anda ' list' - hanya saja jika Anda melakukannya, Anda tidak dapat gunakan lebih lama std::listtanpa membuatnya memenuhi syarat. Itu tidak berbeda dengan jika tidak ada using namespace std;perintah " ". Atau apakah saya melewatkan sesuatu?
Michael Burr
17

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 Xkemudian hampir tanpa risiko dan tidak melakukannya mengarah ke kode yang terlihat bodoh PrefixNS::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

typedef struct list {} list;

Kami harus mengintegrasikan dan menyesuaikan beberapa kode (yang akan saya beri nama "mesin") yang terlihat seperti ini:

#include <list>
...
using std::list;
...
void foo(list const&) {}

Jadi kami memodifikasi seperti ini:

#include <list>

#include "module.h"
...
using std::list;
...
void foo(list const&) {}

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.

Pemrogram
sumber
1
Salah satu kasus terkontrol yang menurut saya menggunakan namespace dapat diterima adalah dalam kode penerbitan. Penyederhanaan memfasilitasi tata letak halaman dan membantu berkonsentrasi pada titik yang terbuka. Kekurangannya adalah ini tidak benar-benar menunjukkan praktik yang baik, jadi saya tidak akan menggunakannya di buku untuk pemula.
Pemrogram
1
Saya pikir mengetik std :: adalah harga kecil yang harus dibayar untuk kejelasan
paoloricardo
4
@paoloricardo: Di sisi lain, saya pikir memiliki std :: muncul di semua tempat adalah kekacauan visual yang tidak perlu.
Michael Burr
1
@ Michael: Anda membayar uang Anda dan Anda membuat pilihan!
paoloricardo
2
Terima kasih telah meluangkan waktu untuk menambahkan detail masalah yang Anda hadapi.
Michael Burr
4

Jika Anda tidak memiliki risiko konflik nama dalam kode Anda dengan std dan pustaka lain, Anda dapat menggunakan:

using namespace std;

Tetapi jika Anda ingin mengetahui dengan tepat ketergantungan kode Anda untuk dokumentasi atau ada risiko konflik nama gunakan cara lain:

using std::string;
using std::cout;

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

Matthieu
sumber
4

Kedua

using std::string;

dan

using namespace std;

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.

Tadeusz Kopec
sumber
3

Bagi saya, saya lebih suka menggunakan ::bila memungkinkan.

std::list<int> iList;

Saya benci menulis:

for(std::list<int>::iterator i = iList.begin(); i != iList.end(); i++)
{
    //
}

Mudah-mudahan, dengan C ++ 0x saya akan menulis ini:

for(auto i = iList.begin(); i != iList.end(); i++)
{
    //
}

Jika namespace sangat panjang,

namespace dir = boost::filesystem;

dir::directory_iterator file("e:/boost");
dir::directory_iterator end;

for( ; file != end; file++)
{
    if(dir::is_directory(*file))
        std::cout << *file << std::endl;
}
AraK
sumber
@AraK: namespace dir = boost :: filesystem; Saya kira ini alias?
paoloricardo
@paoloricardo: Ya, itulah #
sbi
2
Iterator harus ditambah dengan ++i, bukan i++karena, jika itu didefinisikan, membuat salinan sementara iterator yang tidak perlu.
Felix Dombek
2

Anda tidak boleh berada using namespace stddi cakupan namespace di header. Juga, saya kira sebagian besar programmer akan bertanya-tanya kapan mereka melihat vectoratau stringtidak std::, jadi menurut saya tidak using namespace stdlebih baik. Oleh karena itu saya berdebat untuk tidak pernah menjadi using namespace stdsama 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 usingbiasanya 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::swapyang diperlukan (terutama dalam kode generik) untuk mengambil kelebihan beban swap()yang tidak dapat dimasukkan ke dalam stdnamespace (karena kami tidak diizinkan untuk meletakkan kelebihan stdfungsi ke dalam namespace ini).

sbi
sumber
3
Spesialisasi std :: swap akan menjadi spesialisasi yang lengkap - Anda tidak dapat mengkhususkan sebagian template fungsi. Program apa pun diizinkan untuk mengkhususkan sebagian template pustaka standar apa pun selama spesialisasi itu bergantung pada tipe yang ditentukan pengguna.
CB Bailey
@ Charles: Ya, Anda benar, tentu saja, tidak ada FTPS. Dan saya dapat mengkhususkan template di dalamnya std, tetapi tidak kelebihan beban. Maaf untuk brainfart itu. Saya akan mengoreksi postingan tersebut.
sbi
2
Saya juga tidak berpikir maksud dari using namespaceperintah 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 sedikit std::kekacauan. Tapi itu mungkin karena kemampuan perseptif pribadi; beberapa orang menyaringnya std::atau bahkan membutuhkannya sebagai panduan (seperti serif), yang lain tersandung dan merasa seperti berada di jalan yang bergelombang.
Lumi
1
@sbi: Tidak, itu tidak objektif. Itu tergantung pada apakah menurut Anda std :: membantu, atau tidak rapi. Lebih banyak kekacauan -> kurang jelas.
Joshua Richardson
2

Namespaces menyimpan kode untuk mencegah kebingungan dan polusi tanda tangan fungsi.

Berikut demo lengkap dan terdokumentasi tentang penggunaan namespace yang benar :

#include <iostream>
#include <cmath>  // Uses ::log, which would be the log() here if it were not in a namespace, see /programming/11892976/why-is-my-log-in-the-std-namespace

// Silently overrides std::log
//double log(double d) { return 420; }

namespace uniquename {
    using namespace std;  // So we don't have to waste space on std:: when not needed.

    double log(double d) {
        return 42;
    }

    int main() {
        cout << "Our log: " << log(4.2) << endl;
        cout << "Standard log: " << std::log(4.2);
        return 0;
    }
}

// Global wrapper for our contained code.
int main() {
    return uniquename::main();
}

Keluaran:

Our log: 42
Standard log: 1.43508
Cees Timmerman
sumber
1

using namespace stdmengimpor konten stdnamespace saat ini. Jadi, keuntungannya adalah Anda tidak perlu mengetik std::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 stdmencegah 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 namespacefile 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.

Wookai
sumber
2
using namespace std;mengimpor konten stdnamespace ke dalam namespace global. Itu tidak mengubah namespace default. Mendefinisikan sesuatu di namespace global setelah a using namespace stdtidak akan secara ajaib memasukkannya ke dalam stdnamespace.
CB Bailey
Maaf, bukan itu yang saya maksud. Terima kasih telah menunjukkannya, saya akan mengoreksi jawaban saya.
Wookai
1
Guys: terima kasih atas tanggapannya. Tampaknya, secara umum, lebih aman untuk tidak menggunakan 'using namespace std' dan menghindari potensi ambiguitas. Pada keseimbangan menggunakan 'std :: xxx' lebih menarik bagi saya daripada mendeklarasikan daftar berbagai fungsi di awal file sumber karena itu memenuhi syarat dengan jelas apa maksud seseorang.
paoloricardo
1
Kutipan (kecuali jika namespace terlalu panjang). Anda dapat menggunakan namespace aliasing untuk membantu di sana. 'namespace Rv1 = Thor :: XML :: XPath :: Rules :: Light :: Version1;' Catat alias dan gunakan keduanya mematuhi aturan pelingkupan;
Martin York
0

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 stddi 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 baik using namespace std(saat menggunakan berbagai kelas) atau individu using(saat menggunakan beberapa kelas sering).

Sam Brightman
sumber
0

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, atau BuzFlox::Obs::stringkelasnya?

Saat mendesain aliran kontrol, saya bahkan tidak tertarik pada jenis variabel, tapi saya ingin fokus pada if's dan while' dan continue'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.

xtofl
sumber
0

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


sumber
-1

Apa pro dan kontra dari masing-masing

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.

Martin Beckett
sumber
Namespaces tidak benar-benar dirancang untuk memungkinkan penggantian nama dengan fungsionalitas yang berbeda, tetapi setara. Mereka dirancang untuk mencegah bentrokan nama yang tidak diinginkan.
Michael Burr
Ya, jadi satu-satunya pembenaran untuk perintah 'using' yang memutus ini adalah untuk memungkinkan Anda beralih fungsi ke namespace baru.
Martin Beckett
Saya pikir Anda akan menemukan banyak sekali programmer yang mengeluh tentang betapa merepotkannya namespace keledai itu dan ingin membuangnya ke luar jendela jika tidak ada petunjuk penggunaan. Sejauh yang saya tahu, setiap bahasa yang menggunakan namespace memiliki sesuatu yang mirip dengan direktif penggunaan untuk mengeluarkannya saat Anda ingin mereka menyingkir. Jika arahan itu tidak berguna, mengapa ada di mana-mana?
Michael Burr
Saya pikir "menggunakan" dimaksudkan untuk memungkinkan Anda beralih ke implementasi alternatif daripada menyimpan mengetik 3 huruf. Saya suka menggunakan "std :: Foo" karena ini berfungsi sebagai kontrak kepada programmer bahwa saya menggunakan Foo normal dan mereka tidak perlu memeriksanya. Saya setuju saya tidak ingin mengetik "com.microsoft.visual-studio.standard-library.numbers.int foo", beberapa deklarasi iterator di STL menjadi seperti ini. Python melakukan pekerjaan yang bagus untuk memungkinkan Anda menarik set fungsi yang dihias atau tidak didekorasi dari modul.
Martin Beckett
-1

Mengapa tidak misalnya

typedef std::vector<int> ints_t;
ints_t ints1;
....
ints_t ints2;

bukannya yang berat

std::vector<int> ints1;
...
std::vector<int> ints2;

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

void getHistorgram(std::vector<unsigned int>&, std::vector<unsigned int>&);

yang mana nilai kembaliannya?

Bagaimana sebaliknya

typedef std::vector<unsigned int> values_t;
typedef std::vector<unsigned int> histogram_t;
...
void getHistogram(values_t&, histogram_t&); 
anjing
sumber