ทำไม“ ใช้ namespace std;” ถือว่าเป็นการปฏิบัติที่ไม่ดี?


2640

ฉันได้รับการบอกเล่าจากคนอื่นว่าการเขียน using namespace std;ในรหัสที่เป็นธรรมและที่ฉันควรใช้std::coutและstd::cinโดยตรงแทน

เหตุใดจึงusing namespace std;ถือว่าเป็นวิธีปฏิบัติที่ไม่ดี มันไม่มีประสิทธิภาพหรือมีความเสี่ยงในการประกาศตัวแปรที่ไม่ชัดเจน (ตัวแปรที่ใช้ชื่อเดียวกันกับฟังก์ชั่นในstdเนมสเปซ)? มันส่งผลกระทบต่อประสิทธิภาพหรือไม่


512
อย่าลืมว่าคุณสามารถทำได้: "using std :: cout;" ซึ่งหมายความว่าคุณไม่จำเป็นต้องพิมพ์ std :: cout แต่ไม่ต้องนำเนมสเปซทั้งหมดในเวลาเดียวกัน
บิล

2
@a จ่ายแล้วลิงก์nerd google-styleguide.googlecode.com/svn/trunk/…ไม่ทำงานอีกต่อไป ดูเหมือนว่าลิงค์ใหม่คือgoogle.github.io/styleguide/cppguide.html#Other_C++_Features
MCG

64
โดยเฉพาะอย่างยิ่งการใช้ 'using namespace std' ที่ขอบเขตไฟล์ในไฟล์ส่วนหัว การใช้มันในไฟล์ต้นฉบับ (* .cpp) ที่ขอบเขตไฟล์หลังจากการรวมทั้งหมดนั้นไม่ได้แย่นักเนื่องจากเอฟเฟกต์นั้น จำกัด อยู่ที่หน่วยการแปลเดียว แม้แต่ปัญหาที่น้อยก็คือการใช้มันในฟังก์ชั่นหรือชั้นเรียนเพราะผลกระทบของมันจะถูก จำกัด ให้ฟังก์ชั่นหรือขอบเขตของชั้นเรียน
sh-

5
ฉันจะกีดกันการใช้ใช้ namespaces สั่ง แต่สำหรับที่เฉพาะเจาะจงเช่นstd::literals::chrono_literals, Poco::Data:Keywords, Poco::Unitsและสิ่งที่จะจัดการกับตัวอักษรหรือเทคนิคการอ่าน เมื่อใดก็ตามที่มันอยู่ในส่วนหัวหรือไฟล์การใช้งาน มันอาจจะโอเคในขอบเขตฟังก์ชั่นที่ฉันเดา แต่นอกเหนือจากตัวอักษรและสิ่งของมันไม่มีประโยชน์
Ludovic Zenohate Lagouardette

7
@ จอน: ไม่มีอะไรเกี่ยวข้องกับ namespace std โดยเฉพาะ ความสำคัญของฉันคือตั้งใจที่จะ "ในขอบเขตไฟล์ในไฟล์ส่วนหัว" หากต้องการวางไว้เป็นคำแนะนำ: อย่าใช้ "using namespace" (std หรืออื่น ๆ ) ที่ขอบเขตไฟล์ในไฟล์ส่วนหัว มันก็โอเคที่จะใช้มันในไฟล์การใช้งาน ขออภัยในความคลุมเครือ
sh-

คำตอบ:


2230

สิ่งนี้ไม่เกี่ยวข้องกับประสิทธิภาพเลย แต่ให้พิจารณาสิ่งนี้: คุณใช้สองไลบรารีชื่อ Foo and Bar:

using namespace foo;
using namespace bar;

ทุกอย่างทำงานได้ดีและคุณสามารถโทรBlah()จาก Foo และQuux()จาก Bar ได้โดยไม่มีปัญหา แต่วันหนึ่งคุณอัพเกรดเป็นรุ่นใหม่ของฟู 2.0 Quux()ซึ่งตอนนี้มีฟังก์ชั่นที่เรียกว่า ตอนนี้คุณมีข้อขัดแย้ง: ทั้ง Foo 2.0 และ Bar นำเข้าQuux()สู่เนมสเปซส่วนกลางของคุณ นี่จะใช้ความพยายามในการแก้ไขโดยเฉพาะอย่างยิ่งหากพารามิเตอร์ของฟังก์ชันตรงกัน

หากคุณเคยใช้foo::Blah()และbar::Quux()จากนั้นการแนะนำของfoo::Quux()จะเป็นเหตุการณ์ที่ไม่


435
ฉันชอบ "นำเข้า big_honkin_name เป็น bhn" ของ Python เสมอดังนั้นคุณจึงสามารถใช้ "bhn.something" มากกว่า "big_honkin_name.something" ได้อย่างแท้จริง - ลดการพิมพ์ลงได้ C ++ มีลักษณะเช่นนั้นหรือไม่?
paxdiablo

764
@Pax namespace io = boost :: ระบบไฟล์;
214 AraK

152
ฉันคิดว่ามันเป็นการพูดเกินจริงที่จะพูดว่าเป็น "ความพยายามแก้ไข" คุณจะไม่มีอินสแตนซ์ของ foo :: Quux ดังนั้นเพียงยกเลิกการใช้งานในปัจจุบันกับ bar :: Quux
MattyT

289
บุคคลที่มีเหตุผลจะสร้างไลบรารีที่มีชนิดที่มีชื่อที่ไม่ถูกต้องชนกับประเภท std หรือไม่
erikkallen

94
@TomA: ปัญหา#defineคือมันไม่ได้ จำกัด ตัวเองในเนมสเปซ แต่เหยียบย่ำเหนือฐานรหัสทั้งหมด นามแฝง namespace คือสิ่งที่คุณต้องการ
sbi

1391

ฉันเห็นด้วยกับทุกสิ่งที่Greg เขียนแต่ฉันต้องการเพิ่ม: มันอาจแย่ลงกว่าที่ Greg บอก!

Library Foo 2.0 สามารถแนะนำฟังก์ชั่นQuux()ซึ่งเป็นการจับคู่ที่ดีกว่าอย่างไม่น่าเชื่อสำหรับการโทรของคุณQuux()มากกว่าbar::Quux()รหัสที่คุณโทรมานานหลายปี จากนั้นรหัสของคุณยังคงรวบรวมแต่มันเงียบเรียกฟังก์ชั่นที่ไม่ถูกต้องและทำ god-Know-what นั่นเป็นเรื่องไม่ดีเท่าที่จะได้รับ

เก็บไว้ในใจว่าstdnamespace มีตันของตัวระบุหลายแห่งซึ่งมีมากคนทั่วไป (คิดว่าlist, sort, string, iteratorฯลฯ ) ซึ่งมีโอกาสมากที่จะปรากฏในรหัสอื่น ๆ ด้วย

หากคุณคิดว่าสิ่งนี้ไม่น่าเป็นไปได้: มีคำถามถามที่นี่ใน Stack Overflow ที่เกิดเหตุการณ์นี้ขึ้นอย่างมาก (ฟังก์ชั่นผิดที่เรียกว่าเนื่องจากstd::คำนำหน้าที่ละไว้) ประมาณครึ่งปีหลังจากที่ฉันตอบคำถามนี้ นี่เป็นอีกตัวอย่างล่าสุดของคำถามดังกล่าว นี่เป็นปัญหาที่แท้จริง


นี่คือจุดข้อมูลเพิ่มเติมที่หนึ่ง: std::หลายหลายปีที่ผ่านมาผมยังใช้เพื่อพบว่ามันน่ารำคาญต้องทุกอย่างคำนำหน้าจากห้องสมุดมาตรฐานที่มี จากนั้นฉันทำงานในโครงการที่ตัดสินใจเมื่อเริ่มต้นว่าทั้งusingคำสั่งและการประกาศถูกแบนยกเว้นขอบเขตหน้าที่ คาดเดาอะไร พวกเราส่วนใหญ่ใช้เวลาไม่กี่สัปดาห์ในการทำความคุ้นเคยกับการเขียนคำนำหน้าและหลังจากนั้นอีกไม่กี่สัปดาห์พวกเราส่วนใหญ่ก็เห็นด้วยว่าจริงๆแล้วมันทำให้โค้ดอ่านง่ายขึ้น มีเหตุผลคือ: ไม่ว่าคุณจะชอบร้อยแก้วสั้นหรือยาวเป็นเรื่องส่วนตัว แต่คำนำหน้าเพิ่มความชัดเจนให้กับรหัส ไม่เพียง แต่คอมไพเลอร์เท่านั้น แต่คุณเองก็พบว่ามันง่ายกว่าที่จะเห็นตัวบ่งชี้ที่ถูกอ้างถึง

ในทศวรรษโครงการนั้นมีรหัสหลายล้านบรรทัด เนื่องจากการสนทนาเหล่านี้เกิดขึ้นซ้ำแล้วซ้ำอีกฉันเคยสงสัยว่าขอบเขตของฟังก์ชั่น (ได้รับอนุญาต) usingถูกใช้จริงในโครงการ ฉัน grep'd แหล่งที่มาของมันและพบเพียงหนึ่งหรือสองโหลที่มันถูกใช้ สำหรับฉันแล้วสิ่งนี้บ่งชี้ว่าเมื่อได้ลองแล้วนักพัฒนาก็ไม่รู้สึกstd::เจ็บปวดพอที่จะจ้างโดยใช้คำสั่งแม้ทุก ๆ 100 kLoC แม้จะได้รับอนุญาตให้ใช้ก็ตาม


บรรทัดล่าง: คำนำหน้าอย่างชัดเจนทุกอย่างไม่ได้ทำอันตรายใด ๆ ใช้เวลาน้อยในการทำความคุ้นเคยและมีข้อได้เปรียบตามวัตถุประสงค์ โดยเฉพาะอย่างยิ่งมันทำให้โค้ดตีความได้ง่ายขึ้นโดยคอมไพเลอร์และโดยผู้อ่านของมนุษย์ - และนั่นอาจเป็นเป้าหมายหลักเมื่อเขียนโค้ด


140
มันจะเป็นอันตรายต่อความหนาแน่นของรหัสที่คุณสามารถบรรจุในบรรทัดเดียว คุณเขียนโค้ดด้วยวิธียืดยาว ซึ่งลดความสามารถในการอ่าน โดยส่วนตัวฉันคิดว่ารหัสที่สั้นกว่า (แต่ไม่สั้นเกินไป) มีแนวโน้มที่จะอ่านได้ง่ายขึ้น (เนื่องจากมีสิ่งที่ต้องอ่านน้อยลงและสิ่งที่น้อยกว่าที่จะทำให้เสียสมาธิ)
Lie Ryan

91
ลองเดาดูสิว่าคุณพลาดไปเมื่อวันก่อนที่ C ++ จะมีstringระดับมาตรฐานและดูเหมือนว่าห้องสมุดทุกแห่งมีของตัวเอง บอกคุณว่า: เราจะเขียนโค้ดของเราต่อไปstd::และคุณสามารถเรียกใช้รหัสของเราผ่านgrep -v std:: | vimเมื่อคุณเรียกดู หรือคุณสามารถสอนตัวแก้ไขของคุณว่าstd::เป็นคำหลักที่ต้องใช้สีเหมือนกับสีพื้นหลัง อะไรก็ตามที่ใช้งานได้
Mike DeSimone

79
ฉันไม่คิดว่าstd::จะเป็นอันตรายเลย มันมีข้อมูลที่สำคัญมาก (คือ "อะไรก็ตามที่เกิดขึ้นหลังจากนั้นเป็นส่วนหนึ่งของไลบรารีมาตรฐาน" และยังคงเป็นคำนำหน้าสั้น ๆ และกะทัดรัดส่วนใหญ่ไม่มีปัญหาเลยบางครั้งคุณมีโค้ดไม่กี่บรรทัด โดยที่คุณต้องอ้างถึงสัญลักษณ์เฉพาะในstdเนมสเปซจำนวนมากจากนั้นusingคำสั่งในขอบเขตนั้นจะช่วยแก้ปัญหาได้อย่างดี แต่ในกรณีทั่วไปมันไม่มีเสียงรบกวนมันสื่อถึงข้อมูลที่มีค่านอกเหนือจากการลบความคลุมเครือ
jalf

146
เมื่อใดก็ตามที่ฉันเห็นstd::ฉันรู้ว่ามันจะมาจากstd::โดยไม่ต้องคิดเกี่ยวกับมัน ถ้าผมเห็นstringหรือlistหรือmapด้วยตัวเองผมสงสัยนิด
Mateen Ulhaq

67
@LieRyan โชคดีจากนั้นเขียนห้องสมุดเรขาคณิตโดยไม่เคยตั้งชื่อบางสิ่งบางอย่างvector, หรือtransform distanceและนี่เป็นเพียงตัวอย่างของชื่อสามัญจำนวนมากที่ใช้ในไลบรารีมาตรฐาน แนะนำให้ไม่ใช้พวกเขาด้วยความหวาดกลัวหรือความเห็นที่เอนเอียงของคุณลักษณะเนมสเปซที่เป็นส่วนสำคัญของ C ++ ค่อนข้างที่จะต่อต้าน
Christian Rau

420

ปัญหาusing namespaceในการใส่ไฟล์ส่วนหัวของคลาสของคุณคือมันบังคับให้ทุกคนที่ต้องการใช้คลาสของคุณ (โดยรวมไฟล์ส่วนหัวของคุณ) ให้เป็น 'ใช้' (เช่นเห็นทุกอย่างใน) namespaces อื่น ๆ เหล่านั้น

อย่างไรก็ตามคุณอาจใส่คำสั่งที่ใช้ในไฟล์ (ส่วนตัว) * .cpp ของคุณ


ระวังว่าบางคนไม่เห็นด้วยกับคำพูดของฉัน "รู้สึกฟรี" เช่นนี้ - เพราะแม้ว่าusingคำสั่งในไฟล์ cpp จะดีกว่าในส่วนหัว (เพราะมันไม่ส่งผลกระทบต่อคนที่รวมไฟล์ส่วนหัวของคุณ) พวกเขาคิดว่ามันยังไม่ดี (เพราะขึ้นอยู่กับรหัสมันสามารถทำให้การใช้งานในชั้นเรียนยากขึ้น) รายการ C-Super-FAQ นี้บอกว่า

มีการใช้คำสั่งสำหรับรหัส C ++ ดั้งเดิมและเพื่อให้ง่ายต่อการเปลี่ยนไปใช้เนมสเปซ แต่คุณอาจไม่ควรใช้มันเป็นประจำอย่างน้อยก็ไม่ใช่รหัส C ++ ใหม่ของคุณ

คำถามที่พบบ่อยแนะนำทางเลือกสองทาง:

  • การประกาศใช้:

    using std::cout; // a using-declaration lets you use cout without qualification
    cout << "Values:";
  • เพียงพิมพ์ std ::

    std::cout << "Values:";

1
แน่นอนคุณไม่ควรถือว่าสถานะของการแข่งขันระดับโลกอย่างใดอย่างหนึ่งเพื่อมิให้ใครบางคนมี std: cout << std :: hex และล้มเหลวในการ std :: restore_cout_state หลังจากนั้น แต่นั่นคือไขมันอื่น ๆ ทั้งหมด
Móż

233

ฉันเพิ่งวิ่งเข้าไปร้องเรียนเกี่ยวกับVisual Studio 2010 ปรากฎว่าไฟล์ต้นฉบับทั้งหมดมีสองบรรทัดนี้:

using namespace std;
using namespace boost;

คุณสมบัติBoostจำนวนมากกำลังเข้าสู่มาตรฐาน C ++ 0x และ Visual Studio 2010 มีคุณสมบัติ C ++ 0x มากมายดังนั้นทันใดนั้นโปรแกรมเหล่านี้ไม่ได้รวบรวม

ดังนั้นการหลีกเลี่ยงusing namespace X;เป็นรูปแบบของการพิสูจน์อักษรในอนาคตวิธีการทำให้แน่ใจว่าการเปลี่ยนแปลงในไลบรารีและ / หรือไฟล์ส่วนหัวที่ใช้งานอยู่จะไม่ทำให้โปรแกรมแตก


14
นี้. Boost และ STD มีจำนวนมากของการทับซ้อน - โดยเฉพาะอย่างยิ่งตั้งแต่ C ++ 11
einpoklum

1
ฉันทำอย่างนั้นครั้งเดียวและเรียนรู้บทเรียนอย่างหนัก ตอนนี้ฉันไม่เคยใช้usingคำจำกัดความของฟังก์ชั่นนอกและไม่ค่อยได้ใช้using namespaceเลย
Ferruccio

210

เวอร์ชั่นย่อ: อย่าใช้usingการประกาศหรือคำสั่งโกลบอลในไฟล์ส่วนหัว อย่าลังเลที่จะใช้มันในไฟล์การใช้งาน นี่คือสิ่งที่Herb SutterและAndrei Alexandrescuพูดถึงเกี่ยวกับปัญหานี้ในมาตรฐานการเข้ารหัส C ++ (ซึ่งเป็นสิ่งสำคัญสำหรับฉัน):

สรุป

การใช้เนมสเปซมีไว้เพื่อความสะดวกของคุณไม่ใช่เพื่อให้คุณทำดาเมจกับผู้อื่น: อย่าเขียนคำประกาศการใช้หรือคำสั่งการใช้ก่อนหน้าคำสั่ง #include

ข้อสรุป: ในไฟล์ส่วนหัวอย่าเขียนเนมสเปซระดับโดยใช้คำสั่งหรือใช้การประกาศ แต่ให้กำหนดชื่อทั้งหมดแทนอย่างชัดเจน (กฎข้อที่สองต่อจากกฎข้อแรกเนื่องจากส่วนหัวไม่สามารถรู้ได้ว่าส่วนหัว #includes อื่น ๆ อาจปรากฏขึ้นหลังจากพวกเขา)

อภิปรายผล

กล่าวโดยย่อ: คุณสามารถและควรใช้เนมสเปซโดยใช้การประกาศและคำสั่งอย่างอิสระในไฟล์การใช้งานของคุณหลังจาก #include คำสั่งและรู้สึกดีกับมัน แม้จะมีการยืนยันซ้ำไปซ้ำมาในทางตรงกันข้ามเนมสเปซที่ใช้การประกาศและคำสั่งไม่ได้เลวร้ายและพวกเขาจะไม่เอาชนะวัตถุประสงค์ของเนมสเปซ แต่เป็นสิ่งที่ทำให้เนมสเปซสามารถใช้งานได้


4
เพียงความเห็นหนึ่งโปรแกรมเมอร์มากขึ้นที่นี่ แต่ในขณะที่ผมเห็นด้วย 100% กับคำว่าคำว่าusingไม่ควรปรากฏในส่วนหัวของผมไม่เป็นความเชื่อมั่นเกี่ยวกับใบอนุญาตฟรีไปยังสถานusing namespace xyz;ที่ใดก็ได้ในรหัสของคุณโดยเฉพาะอย่างยิ่งถ้ามีxyz stdฉันใช้using std::vector;แบบฟอร์มเนื่องจากเพียงดึงองค์ประกอบเดียวจากเนมสเปซไปสู่ขอบเขตหลอกระดับโลกจึงนำไปสู่ความเสี่ยงต่อการชนน้อยลง
dgnuff

2
@Lightness Races ในวงโคจรคุณมีสิทธิ์ได้รับความคิดเห็นของคุณ จะมีประโยชน์มากกว่านี้หากมีการพยายามอธิบายเหตุผลที่คุณไม่เห็นด้วยกับคำแนะนำที่ให้ไว้ในคำตอบนี้ โดยเฉพาะอย่างยิ่งจะน่าสนใจที่จะเข้าใจว่าจุดของเนมสเปซคืออะไรหาก 'ใช้' พวกเขาไม่ดี? ทำไมไม่เพียงแค่ตั้งชื่อ std_cout แทน std :: cout ... ผู้สร้าง C ++ / namespace จะต้องมีความคิดบางอย่างเมื่อพวกเขาใส่ใจที่จะสร้างมันขึ้นมา
nyholku

1
@nyholku: ไม่จำเป็น - คำตอบส่วนใหญ่ให้เหตุผลเดียวกับที่ฉันต้องการ นอกจากนี้โปรดอย่าลังเลที่จะบันทึก ":)" ฉันเพิ่มความคิดเห็นของฉัน! และฉันไม่ได้บอกว่าเนมสเปซไม่ดี
Lightness Races ที่ Orbit

ใช่ฉันสังเกตเห็นว่า :) แต่ IMO คำตอบส่วนใหญ่ (ที่ขัดแย้งกับคำแนะนำของปราชญ์นี้) นั้นเข้าใจผิด (ไม่ใช่ว่าฉันได้ทำสถิติใด ๆ ที่เป็นเสียงส่วนใหญ่ในขณะนี้) หากคุณยอมรับว่าเนมสเปซนั้น 'ไม่เลว' คุณอาจพูดว่าคุณคิดว่าชื่อเหล่านั้นเหมาะสมหรือไม่ถ้าคุณไม่เห็นด้วยกับคำตอบนี้?
nyholku

ฉันอดไม่ได้ที่using namespaceจะรู้สึกว่าเป็นสิ่งgotoชั่วร้าย ทั้งสองมีการใช้ที่ถูกต้อง แต่ 999 ครั้งจาก 1,000 ครั้งพวกเขาจะใช้ผิด ดังนั้นใช่ด้วยusing namespaceในแหล่งที่คุณจะไม่ทำให้เสียเนมสเปซของอื่น ๆ รวมถึงเรียบร้อย แต่มันจะไม่ปกป้องคุณจาก"ความสนุก"ที่เกิดขึ้นจากusing namespace Foo+ using namespace Barเมื่อคุณโทรหา (โดยปริยาย Foo: :) baz(xyz)และทันใดนั้นการทำลายรหัส (โดยไม่มีการเปลี่ยนแปลงที่เกี่ยวข้อง) เพียงเพราะBar::baz()มีการเพิ่มที่ไหนสักแห่งที่ดีขึ้น จับคู่ (และตอนนี้ถูกเรียกแทน)
CharonX

122

ไม่ควรใช้usingคำสั่งที่ขอบเขตทั่วโลกโดยเฉพาะในส่วนหัว อย่างไรก็ตามมีสถานการณ์ที่เหมาะสมแม้ในไฟล์ส่วนหัว:

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));
}

สิ่งนี้ดีกว่าการรับรองที่ชัดเจน ( std::sin, std::cos... ) เพราะสั้นกว่าและมีความสามารถในการทำงานกับชนิดจุดลอยที่ผู้ใช้กำหนด (ผ่านการค้นหาแบบอิงอาร์กิวเมนต์ (ADL))


9
ฉันขอโทษ แต่ฉันไม่เห็นด้วยอย่างยิ่งกับสิ่งนี้
Billy ONeal

4
@Billy: ไม่มีวิธีอื่นที่จะสนับสนุนการเรียก userlib :: cos (userlib :: superint) ทุกคุณสมบัติมีการใช้งาน
Zan Lynx

17
@Zan: แน่นอนมี using std::cos;, using std::sinฯลฯ ปัญหาว่าเป็นที่ใด ๆ ที่ออกแบบมาอย่างดีuserlibเป็นไปได้ของพวกเขาsinและcosภายใน namespace ของตัวเองเช่นกันดังนั้นนี้จริงๆไม่ช่วยให้คุณ (เว้นแต่จะมีusing namespace userlibเทมเพลตนี้มาก่อนและมันก็แย่using namespace std- และขอบเขตไม่ จำกัด ) นอกจากนี้ฟังก์ชั่นเดียวเช่นนี้ที่ฉันเคยเห็นสิ่งนี้เกิดขึ้นคือswapและในกรณีเช่นนี้ฉันอยากจะแนะนำแค่สร้างเทมเพลต ความเชี่ยวชาญstd::swapและการหลีกเลี่ยงปัญหาทั้งหมด
Billy ONeal

11
@BillyONeal: template<typename T> void swap(MyContainer<T>&, MyContainer<T>&)(ไม่มีฟังก์ชั่นบางส่วนแม่แบบเชี่ยวชาญ (FTPS) ดังนั้นบางครั้งคุณจำเป็นต้องรีสอร์ทเพื่อการบรรทุกเกินพิกัดแทน.
เอสบีไอ

38
@BillyONeal: คุณ (7 ครั้ง upvoted!) แสดงความคิดเห็นเป็นสิ่งที่ผิด - สถานการณ์ที่คุณอธิบายเป็นว่าสิ่งที่ ADL ถูกออกแบบมาเพื่อปก สั้น ๆ หากxมี "เนมสเปซที่เกี่ยวข้อง" อย่างน้อยหนึ่งรายการ (เช่นถ้ามีการกำหนดไว้ในnamespace userlib) การเรียกใช้ฟังก์ชันใด ๆ ที่ดูเหมือนcos(x)จะเพิ่มเติมในเนมสเปซเหล่านั้นด้วยโดยไม่จำเป็นต้องมีอะไรusing namespace userlib;มาก่อน Zan Lynx ถูกต้อง (และการค้นหาชื่อ C ++ คือ Byzantine ... )
j_random_hacker

97

อย่าใช้ทั่วโลก

ก็ถือว่า "เลว" เท่านั้นเมื่อใช้ทั่วโลก เพราะ:

  • คุณถ่วง namespace ที่คุณกำลังเขียนโปรแกรม
  • ผู้อ่านจะมีปัญหาในการดูว่าตัวระบุเฉพาะมาจากไหนเมื่อคุณใช้หลาย ๆusing namespace xyzตัว
  • สิ่งที่เป็นจริงสำหรับผู้อ่านคนอื่น ๆของซอร์สโค้ดของคุณจะเป็นจริงมากขึ้นสำหรับผู้อ่านที่พบบ่อยที่สุดของมัน: ตัวคุณเอง กลับมาในปีหรือสองปีและดู ...
  • หากคุณเพียงพูดถึงusing namespace stdคุณอาจไม่ได้ตระหนักถึงสิ่งที่คุณคว้า - และเมื่อคุณเพิ่มอีก#includeหรือย้ายไปที่การแก้ไข C ++ ใหม่คุณอาจได้รับความขัดแย้งชื่อคุณไม่ได้ตระหนักถึง

คุณสามารถใช้ภายในเครื่อง

ไปข้างหน้าและใช้ในเครื่อง (เกือบ) ได้อย่างอิสระ แน่นอนว่านี่เป็นการป้องกันไม่ให้คุณทำซ้ำstd:: - และการทำซ้ำก็ไม่ดีเช่นกัน

สำนวนที่ใช้ในเครื่อง

ใน C ++ 03 มีสำนวน - รหัสสำเร็จรูป - สำหรับการใช้งานswapฟังก์ชั่นสำหรับชั้นเรียนของคุณ ขอแนะนำให้คุณใช้ท้องถิ่นusing namespace std- หรืออย่างน้อย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(...)`
}

นี่เป็นเวทย์มนตร์ต่อไปนี้:

  • คอมไพเลอร์จะเลือกstd::swapสำหรับเช่นvalue_void std::swap(int, int)
  • หากคุณมีการvoid swap(Child&, Child&)ใช้งานเกินพิกัดคอมไพเลอร์จะเลือก
  • หากคุณไม่มีโอเวอร์โหลดนั้นคอมไพเลอร์จะใช้void std::swap(Child&,Child&)และลองทำการสลับที่ดีที่สุด

ด้วย C ++ 11 ไม่มีเหตุผลที่จะใช้รูปแบบนี้อีกต่อไป การใช้งานของstd::swapถูกเปลี่ยนแปลงเพื่อค้นหาเกินพิกัดที่มีศักยภาพและเลือกมัน


5
"การใช้งาน std :: swap ถูกเปลี่ยนเพื่อค้นหาโอเวอร์โหลดที่มีศักยภาพและเลือก" - อะไร? คุณแน่ใจหรือไม่ แม้ว่าจะเป็นความจริงที่ว่าการให้บริการที่กำหนดเองswapในครั้งแรกนั้นไม่สำคัญมากนักใน C ++ 11 อีกต่อไปเนื่องจากstd::swapตัวมันเองมีความยืดหยุ่นมากกว่า แต่std::swapการสับเปลี่ยนการแลกเปลี่ยนแบบกำหนดเองของคุณโดยอัตโนมัตินั่นเป็นสิ่งใหม่สำหรับฉันอย่างแน่นอน (และฉันไม่เชื่อจริงๆ)
Christian Rau

@ CristianRau ฉันคิดว่าใช่ ฉันอ่านสิ่งนี้ดังนั้น เราสามารถถามHoward ได้ตลอดเวลาเขาควรรู้ ฉันกำลังขุดและเครื่องตักดินในขณะนี้ ...
towi

14
แม้ในกรณีแลกเปลี่ยนที่ชัดเจน (และโชคดีที่ร่วมกันมากขึ้น) สำนวนคือการเขียนมากกว่าusing std::swap; using namespace std;สำนวนที่เฉพาะเจาะจงมากขึ้นมีผลข้างเคียงน้อยลงและทำให้รหัสสามารถบำรุงรักษาได้มากขึ้น
Adrian McCarthy

11
ประโยคสุดท้ายนั้นผิด ใน C ++ 11 Std Swap Two Stepได้รับพรอย่างเป็นทางการว่าเป็นวิธีที่ถูกต้องในการโทรswapและสถานที่อื่น ๆ ในมาตรฐานเปลี่ยนไปเพื่อบอกว่าพวกเขาเรียกswapเช่นนั้น (NB ตามที่ระบุไว้ข้างต้นusing std::swapเป็นวิธีที่ถูกต้องไม่ใช่using namespace std) แต่std::swapตัวมันเองก็ไม่ได้เปลี่ยนไปหาคนอื่นswapและใช้มัน หากstd::swapได้รับเรียกแล้วstd::swapใช้
โจนาธาน Wakely

3
มันอาจฉลาดกว่าที่จะพิมพ์using std::swapเฉพาะที่เพื่อลดเนมสเปซโลคัลในขณะเดียวกันก็สร้างรหัสเอกสารด้วยตนเอง คุณไม่ค่อยสนใจใน std namespace ทั้งหมดดังนั้นเพียงแค่เลือกส่วนที่คุณสนใจออกมา
Lundin

79

ถ้าคุณนำเข้าไฟล์ส่วนหัวด้านขวาคุณก็มีชื่อเช่นhex, left, plusหรือcountอยู่ในขอบเขตทั่วโลกของคุณ สิ่งนี้อาจน่าแปลกใจถ้าคุณไม่ทราบว่าstd::มีชื่อเหล่านี้ หากคุณพยายามใช้ชื่อเหล่านี้ในพื้นที่อาจทำให้เกิดความสับสนได้

หากเนื้อหามาตรฐานทั้งหมดอยู่ในเนมสเปซของตัวเองคุณไม่ต้องกังวลเกี่ยวกับการชนกันของชื่อด้วยโค้ดของคุณหรือไลบรารีอื่น ๆ


12
1 distanceไม่ต้องพูดถึง ฉันยังคงต้องการชื่อที่ไม่ผ่านการรับรองแล้วแต่ความเป็นไปได้ในทางปฏิบัติเนื่องจากมันเพิ่มความสะดวกในการอ่านสำหรับฉัน นอกจากนี้ฉันคิดว่าความจริงที่ว่าเรามักจะไม่ได้มีคุณสมบัติในการพูดด้วยปากและยินดีที่จะใช้เวลาในการแก้ไขความคลุมเครือที่เป็นไปได้หมายความว่ามันมีค่าที่จะเข้าใจสิ่งที่เรากำลังพูดถึงโดยไม่มีคุณสมบัติ รหัสซึ่งหมายความว่ามันมีโครงสร้างในลักษณะที่ชัดเจนว่ามันคืออะไรเกี่ยวกับแม้ไม่มีคุณสมบัติ
ไชโยและ hth - Alf

ถึงจะยุติธรรม แต่คุณไม่มีส่วนใหญ่หากคุณไม่ได้รวม<iomanip>ไว้ ยังคงเป็นจุดที่ดี
einpoklum

48

เหตุผลก็คือแปลกใจ

ถ้าฉันเห็นcout << blahแทนที่จะstd::cout << blahคิดว่า: นี่คือcoutอะไร เป็นปกติcoutหรือไม่ มันเป็นอะไรที่พิเศษไหม


25
นี่เรื่องตลกใช่ไหม? ฉันไม่สามารถบอกได้อย่างแท้จริง ถ้าไม่เช่นนั้นฉันก็จะถือว่ามันเป็น 'ปกติ' เว้นแต่คุณจะไม่เชื่อถือรหัสเพราะไม่เช่นนั้นจะเป็นกลิ่นรหัส BEYOND MAJOR, IMO ... และถ้าคุณไม่เชื่อถือรหัสแล้วทำไมคุณถึงใช้มันตั้งแต่แรก? โปรดทราบว่าฉันไม่ได้พูดว่า "ไว้ใจทุกอย่าง !!" แต่นี่ก็ดูจะไกลไปหน่อยถ้าคุณจะบอกว่าจัดการกับห้องสมุดที่มีชื่อเสียงจาก GitHub หรือบางอย่าง
Brent Rittenhouse

28
@BrentRittenhouse coutเป็นตัวอย่างที่ไม่ดีเพราะทุกคนจำได้ แต่ลองนึกภาพfutureในแอพทางการเงิน เป็นสัญญาซื้อหรือขายบางอย่างตามวันที่กำหนดหรือไม่? ไม่มันไม่ใช่ หากรหัสกล่าวว่าstd::futureคุณจะไม่สับสนอย่างง่ายดาย
James Hollis

2
@BrentRittenhouse อาจเป็นตัวอย่างที่ไม่ดีนักมีห้องสมุดที่แตกต่างกันอย่างน้อยสี่แห่ง อาจเป็น "เป็นไลบรารีมาตรฐานหรือไม่ libstdc ++? stl? อย่างอื่น" และไม่ทุกคนไม่รู้จัก std :: cout อย่างน้อยก็โดยเนื้อแท้แล้วมี 6 คนจาก 7 คนที่เราไม่ได้รับ เพราะหลักสูตรการศึกษาไม่ได้ใช้ในการศึกษา ฉันต้องไล่ printfs ออกไป หรือ debugs () - จาก Qt
Swift - Friday Pie

1
จริงๆ? มันสวยมากในตัวอย่างแรกของบทแรกของหนังสือหลายเล่มใน C ++ ถ้ามีอะไรบ้าง (ด้วยการใช้ตัวดำเนินการแทรก) คือC ++ เพียงอันเดียวที่มีคนรู้จัก
mckenzm

@ mckenzm ฉันอาจใส่ไว้ในหนังสือหรือเอกสารประกอบการบรรยายเพื่อลดความยุ่งเหยิง แต่ไม่ใช่ในรหัส
Martin Beckett

45

โปรแกรมเมอร์ที่มีประสบการณ์ใช้สิ่งใดก็ตามในการแก้ปัญหาและหลีกเลี่ยงสิ่งที่สร้างปัญหาใหม่และพวกเขาก็หลีกเลี่ยงส่วนหัวระดับไฟล์โดยใช้คำสั่งด้วยเหตุผลที่แน่นอนนี้

โปรแกรมเมอร์ที่มีประสบการณ์พยายามหลีกเลี่ยงการรับรองชื่อเต็มในไฟล์ต้นฉบับ เหตุผลเล็กน้อยสำหรับเรื่องนี้ก็คือมันไม่ได้สวยงามที่จะเขียนโค้ดเพิ่มเติมเมื่อโค้ดน้อยลงก็เพียงพอแล้วหากไม่มีเหตุผลที่ดีเว้นแต่มีเหตุผลที่ดีเหตุผลสำคัญสำหรับสิ่งนี้คือการปิดการค้นหาขึ้นอยู่กับอาร์กิวเมนต์ (ADL)

อะไรคือเหตุผลที่ดีเหล่านี้ ? บางครั้งโปรแกรมเมอร์ต้องการปิด ADL อย่างชัดเจนในบางครั้งพวกเขาต้องการปิดบัง

ดังนั้นต่อไปนี้ก็โอเค:

  1. ฟังก์ชั่นการใช้ระดับคำสั่งและการใช้ประกาศในการใช้งานฟังก์ชั่น
  2. ซอร์สไฟล์ระดับการใช้ - ประกาศภายในไฟล์ต้นฉบับ
  3. (บางครั้ง) ซอร์สไฟล์ระดับที่ใช้คำสั่ง

43

ผมยอมรับว่ามันไม่ควรจะใช้ทั่วโลก namespaceแต่ก็ไม่ให้ความชั่วร้ายที่จะใช้ในประเทศเช่นเดียวกับใน นี่คือตัวอย่างจาก"ภาษาการเขียนโปรแกรม 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

}

ในตัวอย่างนี้เราได้แก้ไขการปะทะกันของชื่อและความกำกวมที่อาจเกิดขึ้นจากการจัดองค์ประกอบ

ชื่อที่ประกาศอย่างชัดเจนที่นั่น (รวมถึงชื่อที่ประกาศโดยใช้การประกาศเช่นHis_lib::String) มีความสำคัญมากกว่าชื่อที่ทำให้สามารถเข้าถึงได้ในขอบเขตอื่นโดยการใช้คำสั่ง ( using namespace Her_lib)


29

ฉันคิดว่ามันเป็นการปฏิบัติที่ไม่ดีด้วย ทำไม? แค่วันเดียวฉันคิดว่าฟังก์ชั่นของเนมสเปซคือการแบ่งสิ่งของดังนั้นฉันไม่ควรทำลายมันด้วยการโยนทุกอย่างไว้ในกระเป๋าใบเดียว

อย่างไรก็ตามถ้าฉันมักจะใช้ 'cout' และ 'cin' ฉันจะเขียน: using std::cout; using std::cin;ในไฟล์. cpp (ไม่เคยอยู่ในไฟล์ส่วนหัวในขณะที่เผยแพร่ด้วย#include) ผมคิดว่าไม่มีใครเลยที่จะมีสติตั้งชื่อสตรีมหรือcout cin;)


7
นั่นคือการใช้ในท้องถิ่นประกาศเป็นสิ่งที่แตกต่างกันมากจากการใช้คำสั่ง
sbi

25

ดีใจที่ได้เห็นโค้ดและรู้ว่ามันทำอะไร ถ้าฉันstd::coutรู้ฉันรู้ว่านั่นคือcoutกระแสของstdห้องสมุด ถ้าฉันเห็นcoutแล้วฉันก็ไม่รู้ มันอาจเป็นcoutกระแสของstdห้องสมุด หรืออาจมีint cout = 0;สิบบรรทัดที่สูงกว่าในฟังก์ชั่นเดียวกัน หรือstaticตัวแปรที่มีชื่อcoutในไฟล์นั้น มันอาจเป็นอะไรก็ได้

ทีนี้ลองใช้ฐานรหัสล้านเส้นซึ่งไม่ใหญ่มากนักและคุณกำลังค้นหาจุดบกพร่องซึ่งหมายความว่าคุณรู้ว่ามีหนึ่งบรรทัดในหนึ่งล้านบรรทัดนี้ซึ่งไม่ได้ทำในสิ่งที่ควรทำ cout << 1;สามารถอ่านstatic intชื่อcoutเปลี่ยนมันไปทางซ้ายทีละหนึ่งและทิ้งผล กำลังมองหาข้อผิดพลาดฉันต้องตรวจสอบว่า คุณเห็นไหมว่าฉันชอบดูstd::coutจริงๆ

มันเป็นหนึ่งในสิ่งเหล่านี้ที่ดูเหมือนจะเป็นความคิดที่ดีจริงๆถ้าคุณเป็นครูและไม่เคยต้องเขียนและรักษารหัสใด ๆ สำหรับการดำรงชีวิต ฉันชอบดูรหัสที่ (1) ฉันรู้ว่ามันทำอะไร; และ (2) ฉันมั่นใจว่าคนที่เขียนมันรู้ว่ามันทำอะไร


4
คุณจะรู้ได้อย่างไรว่า "std :: cout << 1" ไม่ได้อ่าน int ชื่อคงที่ cout ใน std namespace ขยับโดยหนึ่งและทิ้งผล? คุณจะรู้ได้อย่างไรว่า "<<" ทำอะไร) ??? ... ดูเหมือนว่าคำตอบนี้ไม่ใช่จุดข้อมูลที่ดีที่จะหลีกเลี่ยง 'ใช้'
nyholku

4
หากใครบางคนได้กำหนดมาตรฐานใหม่ :: cout ให้เป็นจำนวนเต็มแสดงว่าปัญหาของคุณไม่ใช่ด้านเทคนิค แต่เป็นสังคม - ใครบางคนมีไว้ให้คุณ (และคุณควรตรวจสอบส่วนหัวทั้งหมดเพื่อหาสิ่งต่าง ๆ เช่น #define true false และอื่น ๆ )
Jeremy Friesner

2
เมื่อฉันเห็นศาลฉันรู้ว่ามันเป็นมาตรฐาน :: เสมอ ถ้าฉันผิดมันเป็นปัญหาของคนที่เขียนรหัสนี้ไม่ใช่ฉัน :)
Tien Do

22

มันคือทั้งหมดที่เกี่ยวกับการจัดการความซับซ้อน การใช้เนมสเปซจะดึงสิ่งต่าง ๆ ในแบบที่คุณไม่ต้องการและอาจทำให้การดีบักยากขึ้น (ฉันว่าอาจเป็นไปได้) การใช้ std :: ทั่วทุกที่ยากต่อการอ่าน (ข้อความเพิ่มเติมและทั้งหมด)

ม้าสำหรับหลักสูตร - จัดการความซับซ้อนของคุณในแบบที่คุณสามารถและรู้สึกดีที่สุด


18

พิจารณา

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


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

class stringstream {  // Uh oh
};

โปรดทราบว่านี่เป็นตัวอย่างง่ายๆ หากคุณมีไฟล์ที่มี 20 ไฟล์และการนำเข้าอื่น ๆ คุณจะมีข้อมูลอ้างอิงมากมายที่จะช่วยแก้ปัญหาได้ สิ่งที่แย่กว่านั้นคือคุณจะได้รับข้อผิดพลาดที่ไม่เกี่ยวข้องในโมดูลอื่น ๆ ขึ้นอยู่กับคำจำกัดความที่ขัดแย้งกัน

มันไม่ได้น่ากลัว แต่คุณจะไม่ต้องปวดหัวด้วยการไม่ใช้มันในไฟล์ส่วนหัวหรือเนมสเปซส่วนกลาง อาจเป็นเรื่องที่ถูกต้องที่จะทำในขอบเขตที่ จำกัด มาก แต่ฉันไม่เคยมีปัญหาในการพิมพ์อักขระห้าตัวเพื่อชี้แจงว่าหน้าที่ของฉันมาจากไหน


18
  1. คุณต้องสามารถอ่านโค้ดที่เขียนโดยคนที่มีสไตล์และความคิดเห็นที่แตกต่างจากคุณ

  2. หากคุณกำลังใช้เท่านั้นcoutไม่มีใครสับสน แต่เมื่อคุณมีเนมสเปซจำนวนมากบินไปรอบ ๆ และคุณเห็นคลาสนี้และคุณไม่แน่ใจว่ามันทำอะไร คุณสามารถเห็นได้อย่างรวดเร็วก่อน "โอ้นี่คือการดำเนินการระบบไฟล์" หรือ "ที่กำลังทำสิ่งที่เครือข่าย"


17

การใช้เนมสเปซจำนวนมากในเวลาเดียวกันนั้นเป็นสูตรสำหรับภัยพิบัติ แต่การใช้เพียงเนมสเปซstdและเนมสเปซเพียงอย่างเดียวstdนั้นไม่ใช่ข้อตกลงที่ยิ่งใหญ่ในความคิดของฉันเพราะการกำหนดใหม่สามารถเกิดขึ้นได้โดยรหัสของคุณเท่านั้น

ดังนั้นให้พิจารณาฟังก์ชั่นเป็นชื่อที่สงวนไว้เช่น "int" หรือ "class" และนั่นคือมัน

ผู้คนควรหยุดยั้งเรื่องนี้ คุณครูของคุณพูดถูก เพียงใช้ ONE namespace นั่นคือจุดรวมของการใช้เนมสเปซตั้งแต่แรก คุณไม่ควรใช้มากกว่าหนึ่งในเวลาเดียวกัน เว้นแต่เป็นของคุณเอง ดังนั้นการนิยามใหม่จะไม่เกิดขึ้นอีก


การสร้างการชนกันไม่ยาก - สั้นสตริงชอบmin, endและlessปรากฏในstd::namespace แต่ยิ่งไปกว่านั้นในขณะนี้ที่std::มีสัญลักษณ์นับพันอยู่ในนั้นมันมีประโยชน์สำหรับผู้อ่านที่จะรู้ว่าสัญลักษณ์ใหม่ที่พวกเขาอาจไม่รู้มาจากไหน
Tom Swirly

std namespace มีอยู่เพราะคนไม่ว่าคุณเพื่อนร่วมงานของคุณหรือคนที่เขียนมิดเดิลแวร์ที่คุณใช้ไม่ได้ฉลาดเสมอไปเกี่ยวกับการวางฟังก์ชั่นใน namespaces ดังนั้นคุณอาจนำเข้าทั้งหมดของ std :: และไม่มีอะไรอื่นในขณะที่ยังคงมีการปะทะกันระหว่างพูดพูด std :: min และมรดกของคนอื่น :: นาที () จากก่อนเวลาที่มันอยู่ใน std
Aiken Drum

14

ฉันเห็นด้วยกับคนอื่น ๆ ที่นี่ แต่ฉันต้องการพูดถึงข้อกังวลเกี่ยวกับความสามารถในการอ่าน - คุณสามารถหลีกเลี่ยงสิ่งเหล่านี้ได้เพียงแค่พิมพ์ typedefs ที่ด้านบนของไฟล์ฟังก์ชันหรือการประกาศคลาส

ฉันมักจะใช้มันในการประกาศชั้นเรียนของฉันเป็นวิธีการในชั้นเรียนมักจะจัดการกับชนิดข้อมูลที่คล้ายกัน (สมาชิก) และ typedef เป็นโอกาสที่จะกำหนดชื่อที่มีความหมายในบริบทของชั้นเรียน สิ่งนี้ช่วยในการอ่านได้จริงในคำจำกัดความของวิธีการเรียน

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

และในการดำเนินการ:

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

ตรงข้ามกับ:

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

หรือ:

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

เพียงแค่ความคิดเห็นเล็กน้อยในขณะที่ typedef มีประโยชน์ฉันควรพิจารณาสร้างคลาสที่แทนบรรทัดแทนการใช้ typedef
Eyal Solnik

14

ตัวอย่างที่ชัดเจนในการชี้แจงข้อกังวล ลองนึกภาพคุณมีสถานการณ์ที่คุณมีห้องสมุดสองแห่งfooและbarแต่ละแห่งมีเนมสเปซของตนเอง:

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

namespace bar {
    ...
}

สมมติว่าคุณใช้fooและbarร่วมกันในโปรแกรมของคุณเองดังนี้:

using namespace foo;
using namespace bar;

void main() {
    a(42);
}

ณ จุดนี้ทุกอย่างดี เมื่อคุณเรียกใช้โปรแกรมมัน 'ทำอะไร' แต่ภายหลังคุณอัปเดตbarและสมมติว่ามันเปลี่ยนเป็นเหมือน:

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

ณ จุดนี้คุณจะได้รับข้อผิดพลาดของคอมไพเลอร์:

using namespace foo;
using namespace bar;

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

ดังนั้นคุณจะต้องทำการบำรุงรักษาบางอย่างที่จะชี้แจงว่า 'a' foo::aหมาย นั่นเป็นสิ่งที่ไม่พึงประสงค์ แต่โชคดีที่มันค่อนข้างง่าย (เพียงเพิ่มfoo::หน้าการเรียกไปยังaเครื่องหมายคอมไพเลอร์ว่าคลุมเครือ)

แต่ลองจินตนาการถึงสถานการณ์ทางเลือกที่แถบเปลี่ยนไปเพื่อให้มีลักษณะเช่นนี้แทน:

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

ณ จุดนี้การเรียกร้องให้คุณa(42)ผูกกับbar::aแทนที่จะfoo::aทำอะไรบางอย่างที่แตกต่างไปจากเดิมอย่างสิ้นเชิง ไม่มีคำเตือนการรวบรวมหรืออะไร โปรแกรมของคุณเพิ่งเริ่มทำสิ่งที่แตกต่างไปจากเดิมอย่างเงียบ ๆ

เมื่อคุณใช้เนมสเปซคุณจะเสี่ยงต่อสถานการณ์เช่นนี้ซึ่งเป็นสาเหตุที่ทำให้คนไม่สบายใจที่ใช้เนมสเปซ ยิ่งมีสิ่งต่าง ๆ ในเนมสเปซมากเท่าใดก็ยิ่งมีความเสี่ยงต่อความขัดแย้งสูงขึ้นดังนั้นผู้คนจึงอาจรู้สึกอึดอัดใจในการใช้เนมสเปซstd(เนื่องจากจำนวนของสิ่งต่าง ๆ ในเนมสเปซนั้น) มากกว่าเนมสเปซอื่น ๆ

ท้ายที่สุดนี่เป็นการแลกเปลี่ยนระหว่างความสามารถในการเขียนทับได้กับความน่าเชื่อถือ / การบำรุงรักษา ความสามารถในการอ่านอาจเป็นปัจจัยในเช่นกัน แต่ฉันสามารถเห็นการโต้เถียงสำหรับวิธีนี้ โดยทั่วไปฉันจะบอกว่าความน่าเชื่อถือและการบำรุงรักษามีความสำคัญมากกว่า แต่ในกรณีนี้คุณจะต้องจ่ายค่าใช้จ่ายในการเขียนได้ตลอดเวลาสำหรับความน่าเชื่อถือ / การบำรุงรักษาที่หายาก การแลกเปลี่ยนที่ดีที่สุดจะเป็นตัวตัดสินโครงการและลำดับความสำคัญของคุณ


สถานการณ์ที่สองเข้าใจข้อตกลงสำหรับฉัน ไม่มีเนมสเปซอีกแล้ว ไม่สามารถทำการเปลี่ยนแปลงเล็กน้อยในฟังก์ชันการทำงานที่ตรวจไม่พบภายใต้ประทุน
safe_malloc

13

เนมสเปซคือขอบเขตที่กำหนดชื่อ Namespaces ใช้เพื่อจัดกลุ่มการประกาศที่เกี่ยวข้องและเพื่อแยกรายการแยกต่างหาก ตัวอย่างเช่นสองไลบรารีที่พัฒนาแยกกันอาจใช้ชื่อเดียวกันเพื่ออ้างถึงไอเท็มที่ต่างกัน แต่ผู้ใช้ยังสามารถใช้ทั้งสอง:

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

การทำซ้ำชื่อเนมสเปซอาจเป็นสิ่งที่ทำให้ไขว้เขวสำหรับทั้งผู้อ่านและผู้เขียน ดังนั้นจึงเป็นไปได้ที่จะระบุว่าชื่อจากเนมสเปซเฉพาะนั้นมีอยู่โดยไม่มีการรับรองที่ชัดเจน ตัวอย่างเช่น:

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

เนมสเปซเป็นเครื่องมือที่ทรงพลังสำหรับการจัดการไลบรารี่ที่แตกต่างกันและโค้ดต่าง ๆ โดยเฉพาะอย่างยิ่งพวกเขาเสนอทางเลือกโปรแกรมเมอร์ของวิธีการที่ชัดเจนในการอ้างอิงถึงชื่อที่ไม่ใช่ท้องถิ่น

ที่มา: ภาพรวมของภาษาการเขียนโปรแกรม C ++ โดย Bjarne Stroustrup


4
น่าสนใจมากที่คำตอบนี้มีพื้นฐานมาจากคำแนะนำจากคนอื่น ๆ ที่ Bjarne Stroustrup ได้รับ -2 ... เด็กชาย Bjarne ต้องเป็นโปรแกรมเมอร์ที่ยากจนและไม่มีประสบการณ์เมื่อเขาแนะนำคุณลักษณะนี้ใน C ++
nyholku

@nyholku: ดูนี้
sbi

10

ตัวอย่างที่using namespace stdเกิดข้อผิดพลาดในการคอมไพล์เนื่องจากความคลุมเครือของการนับซึ่งเป็นฟังก์ชันในไลบรารีอัลกอริทึม

#include <iostream>

using namespace std;

int count = 1;
int main() {
    cout << count << endl;
}

2
::count--แก้ไขปัญหา. โดยปกติคุณจะมีข้อมูลเพิ่มเติมจาก std เนมสเปซมากกว่าจากที่อื่นดังนั้นการรักษาคำสั่ง namespace โดยใช้อาจช่วยให้คุณพิมพ์ได้
PSkocik

ปัญหาจริงที่นี่คือ C ++ ยังคงมี globals น้อยกว่า namespace สิ่งนี้และความจริงที่ว่า 'สิ่งนี้' เป็นนัยในวิธีการทำให้เกิดข้อบกพร่องและปัญหามากมายที่ฉันไม่สามารถนับได้แม้จะมีตัวแปร 'นับ' ที่ถูกต้อง ;)
Aiken Drum

9

ไม่ได้ทำให้ซอฟต์แวร์หรือประสิทธิภาพของโครงการแย่ลง การรวมเนมสเปซที่จุดเริ่มต้นของซอร์สโค้ดของคุณนั้นไม่เลวเลย การรวมusing namespace stdคำสั่งจะแตกต่างกันไปตามความต้องการของคุณและวิธีที่คุณพัฒนาซอฟต์แวร์หรือโครงการ

namespace stdมีฟังก์ชั่นมาตรฐาน C ++ และตัวแปร เนมสเปซนี้มีประโยชน์เมื่อคุณมักจะใช้ฟังก์ชันมาตรฐาน C ++

ตามที่กล่าวไว้ในหน้านี้:

คำสั่งที่ใช้ namespace std โดยทั่วไปถือว่าไม่ดี ทางเลือกสำหรับข้อความนี้คือการระบุเนมสเปซที่ตัวระบุเป็นเจ้าของโดยใช้โอเปอเรเตอร์ขอบเขต (: :) ทุกครั้งที่เราประกาศประเภท

และเห็นความคิดเห็นนี้ :

ไม่มีปัญหาในการใช้ "using namespace std" ในไฟล์ต้นฉบับของคุณเมื่อคุณใช้ namespace หนักและรู้ว่าไม่มีอะไรจะชนกัน

บางคนบอกว่านั่นเป็นวิธีปฏิบัติที่ไม่ดีที่จะรวมไว้using namespace stdในไฟล์ต้นฉบับของคุณเพราะคุณเรียกใช้จากเนมสเปซทั้งหมดของฟังก์ชั่นและตัวแปร เมื่อคุณต้องการที่จะกำหนดฟังก์ชั่นใหม่ที่มีชื่อเดียวกันกับฟังก์ชั่นอื่นที่มีอยู่ในnamespace stdคุณจะเกินฟังก์ชั่นและมันอาจก่อให้เกิดปัญหาเนื่องจากการรวบรวมหรือรัน มันจะไม่รวบรวมหรือดำเนินการตามที่คุณคาดหวัง

ตามที่กล่าวไว้ในหน้านี้:

แม้ว่าคำสั่งจะช่วยเราไม่ให้พิมพ์ std :: เมื่อใดก็ตามที่เราต้องการเข้าถึงคลาสหรือชนิดที่กำหนดใน std namespace มันจะนำเข้า std namespace ทั้งหมดลงใน namespace ปัจจุบันของโปรแกรม ขอให้เรายกตัวอย่างสองสามอย่างเพื่อทำความเข้าใจว่าทำไมสิ่งนี้อาจไม่ใช่สิ่งที่ดี

...

ขณะนี้อยู่ในขั้นตอนของการพัฒนาภายหลังเราต้องการใช้ cout รุ่นอื่นที่นำไปใช้ในห้องสมุดที่เรียกว่า“ foo” (ตัวอย่าง)

...

ขอให้สังเกตว่ามีความกำกวมห้องสมุดไหนชี้ไปที่? คอมไพเลอร์อาจตรวจพบสิ่งนี้และไม่คอมไพล์โปรแกรม ในกรณีที่แย่ที่สุดโปรแกรมอาจยังคงคอมไพล์ แต่เรียกใช้ฟังก์ชันที่ไม่ถูกต้องเนื่องจากเราไม่เคยระบุว่าเนมสเปซตัวใดเป็นของตัวระบุ


8

ฉันไม่คิดว่ามันเป็นการปฏิบัติที่ไม่ดีภายใต้เงื่อนไขทั้งหมด แต่คุณต้องระวังเมื่อคุณใช้ หากคุณกำลังเขียนไลบรารีคุณอาจใช้ตัวดำเนินการแก้ไขปัญหาขอบเขตกับเนมสเปซเพื่อป้องกันไม่ให้ห้องสมุดของคุณปะทะหัวกับห้องสมุดอื่น สำหรับรหัสระดับแอปพลิเคชันฉันไม่เห็นอะไรผิดปกติ


7

"ทำไมจึงเป็น 'using namespace std;' ถือว่าเป็นวิธีปฏิบัติที่ไม่ดีใน C ++ หรือไม่ "

ฉันพูดอีกอย่าง: ทำไมการพิมพ์อักขระพิเศษห้าตัวจึงถือเป็นเรื่องยุ่งยากสำหรับบางคน

พิจารณาเช่นการเขียนซอฟต์แวร์ตัวเลข เหตุใดฉันจึงต้องพิจารณาทำให้เนมสเปซทั่วโลกของฉันมีมลภาวะด้วยการตัด "std :: vector" ทั่วไปลงไปที่ "เวกเตอร์" เมื่อ "เวกเตอร์" เป็นหนึ่งในแนวคิดที่สำคัญที่สุดของโดเมนปัญหา


19
มันไม่ใช่แค่ 5 ตัวอักษรพิเศษ 5 chars พิเศษทุกครั้งที่คุณอ้างอิงประเภทของวัตถุใด ๆ ในไลบรารีมาตรฐาน ซึ่งหากคุณใช้ห้องสมุดมาตรฐานเป็นอย่างมากจะเกิดขึ้นบ่อยครั้ง ดังนั้นมันจึงเป็นชาร์ตพิเศษหลายพันรายการในขนาดที่เหมาะสม สมมุติว่าคำสั่ง 'ใช้' ได้ถูกเพิ่มเข้าไปในภาษาเพื่อให้สามารถใช้ ...
Jeremy Friesner

5
ไม่ใช่ 5 chars พิเศษทุกครั้งมันคือ 5 chars และอาจคลิกเมาส์สองครั้งเพื่อดึงเมนูและทำการค้นหาและแทนที่ในตัวแก้ไขที่คุณเลือก
DaveWalley

1
การอ่าน cout << hex << setw(4) << i << endl;อ่านง่ายกว่าstd::cout << std::hex << std::setw(4) << i << std::endl;
oz1cz

16
และยิ่งเลวร้ายลง: เป็นที่น่ากลัวเมื่อเทียบกับstd::map<std::string,std::pair<std::string,std::string>> map<string,pair<string,string>>
oz1cz

4
เป็นวิธีปฏิบัติที่ดีคือการพิมพ์คอนเทนเนอร์ STL ของคุณแล้ว std :: นั่นไม่สำคัญ และ C ++ 11 ทำให้เราทราบคำหลักอัตโนมัติซึ่งทำให้สิ่งต่าง ๆ ง่ายขึ้นเมื่อใช้ตัววนซ้ำ
juzzlin

7

ฉันเห็นด้วยกับคนอื่น ๆ - มันกำลังขอการปะทะกันของชื่อความคลุมเครือแล้วความจริงก็คือมันไม่ชัดเจน ในขณะที่ฉันเห็นการใช้งานการusingตั้งค่าส่วนตัวของฉันคือ จำกัด ฉันจะพิจารณาสิ่งที่คนอื่นชี้:

หากคุณต้องการค้นหาชื่อฟังก์ชั่นที่อาจเป็นชื่อสามัญ แต่คุณต้องการค้นหาในstdเนมสเปซเท่านั้น (หรือกลับด้าน - คุณต้องการเปลี่ยนการโทรทั้งหมดที่ไม่ได้อยู่ในเนมสเปซstd, เนมสเปซX... ), แล้วคุณจะเสนอให้ทำอย่างไร

คุณสามารถเขียนโปรแกรมเพื่อทำมันได้ แต่มันจะดีกว่าไหมถ้าคุณใช้เวลาทำงานกับโครงการของคุณเองแทนที่จะเขียนโปรแกรมเพื่อดูแลโครงการของคุณ?

โดยส่วนตัวแล้วฉันไม่รังเกียจstd::คำนำหน้า ฉันชอบรูปลักษณ์ที่มากกว่าไม่มี ฉันไม่รู้ว่าเป็นเพราะชัดเจนหรือไม่และบอกกับฉันว่า "นี่ไม่ใช่รหัสของฉัน ... ฉันใช้ไลบรารี่มาตรฐาน" หรือถ้าเป็นอย่างอื่น แต่ฉันคิดว่ามันดูดีกว่า นี่อาจจะแปลกเพราะฉันเพิ่งได้รับใน C ++ (ใช้แล้วและยังคงทำ C และภาษาอื่น ๆ นานกว่านี้และ C เป็นภาษาที่ฉันโปรดปรานตลอดกาลเหนือการชุมนุม)

มีสิ่งหนึ่งที่อื่นแม้ว่ามันจะค่อนข้างเกี่ยวข้องกับข้างต้นและสิ่งที่คนอื่นชี้ให้เห็น แม้ว่านี่อาจเป็นวิธีปฏิบัติที่ไม่ดี แต่บางครั้งฉันก็จองstd::nameรุ่นและชื่อไลบรารีมาตรฐานสำหรับการใช้งานเฉพาะโปรแกรม ใช่แล้วสิ่งนี้อาจกัดคุณและกัดคุณอย่างหนัก แต่ทุกอย่างลงมาที่ฉันเริ่มโครงการนี้ตั้งแต่เริ่มต้นและฉันเป็นโปรแกรมเมอร์คนเดียวสำหรับมัน ตัวอย่าง: ฉันเกินและเรียกมันว่าstd::string stringฉันมีสิ่งที่เป็นประโยชน์เพิ่มเติม ฉันทำบางส่วนเพราะแนวโน้ม C และ Unix (+ Linux) ของฉันที่มีต่อชื่อตัวพิมพ์เล็ก

นอกจากนั้นคุณสามารถมีชื่อแทนเนมสเปซ นี่คือตัวอย่างของที่ที่มีประโยชน์ที่อาจไม่ได้รับการอ้างอิง ฉันใช้มาตรฐาน C ++ 11 และเฉพาะกับ libstdc ++ มันไม่ได้รับstd::regexการสนับสนุนที่สมบูรณ์ แน่นอนว่ามันคอมไพล์ แต่มันมีข้อผิดพลาดตามบรรทัดของมันซึ่งเป็นข้อผิดพลาดในตอนท้ายของโปรแกรมเมอร์ แต่มันก็ขาดการใช้งาน

ดังนั้นนี่คือวิธีที่ฉันแก้ไขมัน ติดตั้ง Regex ของ Boost และเชื่อมโยงระบบจากนั้นฉันทำสิ่งต่อไปนี้เพื่อที่ว่าเมื่อ libstdc ++ ได้ติดตั้งอย่างสมบูรณ์ฉันต้องการเพียงลบบล็อกนี้และรหัสยังคงเหมือนเดิม:

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;
}

ฉันจะไม่โต้แย้งว่ามันเป็นความคิดที่ไม่ดีหรือไม่ อย่างไรก็ตามฉันจะเถียงว่ามันทำให้มันสะอาดสำหรับโครงการของฉันและในเวลาเดียวกันทำให้เจาะจง: จริงฉันต้องใช้ Boost แต่ฉันใช้มันเหมือน libstdc ++ ในที่สุดจะมีมัน ใช่เริ่มโครงการของคุณเองและเริ่มต้นด้วยมาตรฐาน (... ) ที่จุดเริ่มต้นไปไกลมากด้วยการช่วยบำรุงรักษาพัฒนาและทุกอย่างที่เกี่ยวข้องกับโครงการ!

เพียงชี้แจงบางสิ่งบางอย่าง: ฉันไม่คิดว่าเป็นความคิดที่ดีที่จะใช้ชื่อของคลาส / สิ่งใดก็ตามในSTLโดยเจตนาและเฉพาะเจาะจงมากกว่า สตริงเป็นข้อยกเว้น (ไม่สนใจแรกเหนือหรือที่สองที่นี่ถ้าคุณต้องปุน) สำหรับฉันเพราะฉันไม่ชอบความคิดของ 'สตริง'

ตามที่เป็นอยู่ฉันยังคงมีอคติต่อ C และมีอคติต่อ C ++ มาก สิ่งที่ฉันทำงานอยู่เหมาะกับ C มากขึ้น (แต่มันเป็นการออกกำลังกายที่ดีและเป็นวิธีที่ดีที่จะทำให้ตัวเอง a. เรียนรู้ภาษาอื่นและ b. พยายามอย่าลำเอียงกับวัตถุ / คลาส / ฯลฯ ที่น้อยลง เป็นคนใจแคบน้อยยอมรับน้อยและยอมรับมากขึ้น) แต่สิ่งที่มีประโยชน์คือสิ่งที่บางคนแนะนำไปแล้ว: ฉันใช้ลิสต์ (มันค่อนข้างธรรมดาใช่มั้ย?) และเรียงลำดับ (สิ่งเดียวกัน) กับชื่อที่สองที่จะทำให้เกิดการปะทะกันของชื่อหากฉันต้องทำเช่นusing namespace std;นั้น ด้วยเหตุนี้ฉันจึงชอบที่จะมีความเฉพาะเจาะจงในการควบคุมและรู้ว่าถ้าฉันตั้งใจจะให้มันเป็นมาตรฐานการใช้งานแล้วฉันจะต้องระบุมัน พูดง่าย ๆ : ไม่ได้รับอนุญาต

และในขณะที่สำหรับการทำ Boost stdเป็นส่วนหนึ่งของ ฉันทำเพื่อบูรณาการในอนาคตและ - อีกครั้งผมยอมรับอย่างเต็มที่นี้เป็นอคติ - boost::regex:: ...ฉันไม่คิดว่ามันเป็นเรื่องน่าเกลียด แน่นอนว่าเป็นอีกสิ่งหนึ่งสำหรับฉัน มีหลายสิ่งใน C ++ ที่ฉันยังไม่ได้ยอมรับอย่างเต็มที่ในรูปลักษณ์และวิธีการ (ตัวอย่างอื่น: เทมเพลต variadic และอาร์กิวเมนต์ var [แม้ว่าฉันยอมรับเทมเพลต Variadic นั้นมีประโยชน์มาก!]) แม้แต่คนที่ฉันยอมรับก็เป็นเรื่องยากและฉันก็ยังมีปัญหากับพวกเขา



7

จากประสบการณ์ของฉันถ้าคุณมีหลายไลบรารีที่ใช้พูดแต่เพื่อวัตถุประสงค์ที่แตกต่างกันคุณอาจจะใช้ที่ไม่ถูกต้องcoutcout

ตัวอย่างเช่นถ้าผมพิมพ์ในusing namespace std;และusing namespace otherlib;และพิมพ์เพียงcout(ซึ่งเกิดขึ้นที่จะอยู่ในทั้งสอง) มากกว่าstd::cout(หรือ'otherlib::cout'), คุณอาจใช้ผิดหนึ่งและได้รับข้อผิดพลาด มีประสิทธิภาพและใช้งานstd::coutได้มากกว่า


6

ด้วยตัวระบุที่นำเข้าอย่างไม่มีเงื่อนไขคุณต้องใช้เครื่องมือค้นหาภายนอกเช่นgrepเพื่อค้นหาว่ามีการประกาศตัวระบุไว้ที่ใด สิ่งนี้ทำให้การให้เหตุผลเกี่ยวกับความถูกต้องของโปรแกรมหนักขึ้น


6

ขึ้นอยู่กับว่าอยู่ที่ไหน หากเป็นส่วนหัวทั่วไปคุณจะลดค่าของเนมสเปซโดยการรวมเข้าไปในเนมสเปซส่วนกลาง โปรดทราบว่านี่อาจเป็นวิธีที่สะดวกในการสร้างโมดูลกลม


6

นี่เป็นวิธีปฏิบัติที่ไม่ดีซึ่งมักรู้จักกันในชื่อมลภาวะทั่วโลก ปัญหาอาจเกิดขึ้นเมื่อกว่าหนึ่ง namespace มีชื่อฟังก์ชั่นเดียวกันกับลายเซ็นแล้วมันจะไม่ชัดเจนสำหรับคอมไพเลอร์ที่จะตัดสินใจที่หนึ่งที่จะโทรและทั้งหมดนี้สามารถหลีกเลี่ยงได้เมื่อคุณระบุ namespace std::coutที่มีฟังก์ชั่นการโทรของคุณเช่น หวังว่านี่จะช่วยได้ :)


5

เพื่อตอบคำถามของคุณฉันดูมันด้วยวิธีนี้ในทางปฏิบัติ: โปรแกรมเมอร์จำนวนมาก (ไม่ใช่ทั้งหมด) เรียกใช้ namespace std ดังนั้นหนึ่งควรอยู่ในนิสัยของการไม่ใช้สิ่งที่กระทบหรือใช้ชื่อเดียวกันกับสิ่งที่อยู่ใน namespace std นั่นเป็นข้อตกลงที่ได้รับอย่างมาก แต่ไม่มากนักเมื่อเทียบกับจำนวนคำที่เป็นไปได้ที่เชื่อมโยงกันและนามแฝงที่อาจเกิดขึ้นกับการพูดอย่างเคร่งครัด

ฉันหมายถึงจริงๆ ... การพูดว่า "อย่าพึ่งพาสิ่งมีชีวิตนี้" เป็นเพียงการตั้งค่าให้คุณพึ่งพาที่ไม่ได้อยู่ คุณมักจะมีปัญหาในการยืมตัวอย่างโค้ดและทำการซ่อมแซมอย่างต่อเนื่อง เพียงแค่ให้สิ่งที่ผู้ใช้กำหนดและยืมในขอบเขตที่ จำกัด ตามที่ควรจะเป็นและประหยัดมากกับ globals (globals สุจริตเกือบจะเป็นทางเลือกสุดท้ายสำหรับวัตถุประสงค์ของ "รวบรวมตอนนี้สติในภายหลัง") แท้จริงฉันคิดว่ามันเป็นคำแนะนำที่ไม่ดีจากครูของคุณเพราะการใช้ std จะใช้ได้ทั้ง "cout" และ "std :: cout" แต่การไม่ใช้ std จะใช้ได้กับ "std :: cout" เท่านั้น คุณจะไม่โชคดีพอที่จะเขียนโค้ดของคุณเองทั้งหมด

หมายเหตุ: อย่ามุ่งเน้นประเด็นเกี่ยวกับประสิทธิภาพมากเกินไปจนกว่าคุณจะได้เรียนรู้เล็กน้อยเกี่ยวกับการทำงานของคอมไพเลอร์ ด้วยประสบการณ์การเขียนโค้ดเพียงเล็กน้อยคุณไม่จำเป็นต้องเรียนรู้เกี่ยวกับพวกเขามากนักก่อนที่คุณจะรู้ว่าพวกเขาสามารถสร้างรหัสที่ดีให้เป็นสิ่งที่เรียบง่าย ง่ายนิดหน่อยเหมือนกับที่คุณเขียนทุกสิ่งใน C. โค้ดที่ดีนั้นซับซ้อนเท่าที่จำเป็น


เมื่อพิจารณาว่ามีกี่คนที่ไม่รู้สึกถึงฟังก์ชั่นห้องสมุดมาตรฐานที่มีประโยชน์ ( <algorithm>ยกตัวอย่างเช่น countดูรหัสผ่านของคุณเองและบอกฉันว่าคุณไม่เคยมีตัวแปรหรือฟังก์ชั่นที่เรียกว่า หรือdistanceหรือlog, destroy, launch, visit, beta, sample, messages, clamp, erase, copy, modulus, leftฯลฯ ไม่ต้องพูดถึงตัวบ่งชี้ทั้งหมดที่ยังไม่อยู่ในstdที่จะแบ่งรหัสของคุณเมื่อ C ++ 35 ออกมา ...
Toby Speight
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.