เมื่อใดจึงควรใช้ C ผ่าน C ++ และ C ++ เหนือ C


164

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

แต่ฉันเคยเห็นหลาย ๆ กรณีที่โครงการซอฟต์แวร์หรือแม้แต่เล็ก ๆ จะแทรกไฟล์ที่มีจำนวน n ของไฟล์เหล่านั้นจะถูกเขียนใน C และไฟล์ m จำนวนหนึ่งจะถูกเขียนใน C ++

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

ดังนั้นจะเป็นที่นิยมถ้ามีคนสามารถเคลียร์สถานการณ์! ขอบคุณ


4
การใช้ C inline ในรหัส C ++ มักเป็นโมดูลที่จำเป็นต้องปรับให้เหมาะสมทำงานในระดับต่ำมากใกล้กับฮาร์ดแวร์หรือมีความสำคัญอย่างยิ่งต่อความสมบูรณ์ของข้อมูลหรือแม้แต่ความปลอดภัยของมนุษย์และต้องสามารถตรวจสอบและพิสูจน์ได้อย่างถูกต้อง แทนที่จะทำทุกอย่างใน C โครงการส่วนใหญ่สามารถใช้ประโยชน์จากคุณสมบัติ C ++ สำหรับการออกแบบที่ยืดหยุ่นในขณะที่ได้รับประโยชน์จากความหนาแน่นของ C ในสถานที่ที่ต้องการ
kylben

30
@ kylben: ผู้ชาย C ++ หลายคนจะบอกคุณ: (1) ประสิทธิภาพไม่ใช่เหตุผลที่จะลดลงไปที่ C (อาจจะหลีกเลี่ยงvirtualและคุณสมบัติอื่น ๆ อีกสองสามอย่างที่ป้องกันการปรับให้เหมาะสม แต่เช่นไม่ใช่virtualคลาสไม่ได้มีประสิทธิภาพ เครื่องมือที่เป็นนามธรรมที่ทรงพลังซึ่งสามารถนำไปสู่การมีประสิทธิภาพมากขึ้นเช่นqsortvs std::sort) (2) ความสำคัญของความถูกต้องสูงคือเหตุผลที่ใช้ C ++ (typesafety, constness, privateRAII เพื่อให้การจัดการทรัพยากรสามารถจัดการได้ ฯลฯ ) เหนือ C หรือสำหรับเรื่องนั้นให้ใช้ Ada หรือบางสิ่งในตอนแรก

11
@ Pubby8 ฉันไม่เห็นด้วยกับสิ่งนี้ หากฉันกำลังทำงานกับไฟล์. c และฉันเห็นผู้คนทำสิ่งนี้ฉันมักจะแจ้งให้พวกเขาทราบว่าพวกเขากำลังทำอะไรอยู่ ตัวอย่างเช่นไม่จำเป็นต้องส่งvoid*ต่อไปยังตัวชี้ประเภทอื่นในรหัส C มันเป็นสิ่งที่ทำให้เสียสมาธิและเป็นแบบอย่างของคนที่ไม่รู้จัก C.
asveikau

4
@ kylben: (คุณอาจต้องการเรียนรู้ที่จะตอบคำถามของผู้อื่นอย่างถูกต้องในการตอบความคิดเห็นของคุณดังนั้นพวกเขาจึงมีโอกาสได้เห็นพวกเขาจริงๆ ) ว่า "โปรแกรมเมอร์คุ้นเคยกับวิธีที่คอมไพเลอร์เปลี่ยน C เป็น asm" ดี. แต่นั่นไม่เกี่ยวข้องง่ายๆ: ถ้าคุณต้องการตะลุย asm เพียงแค่เขียน asm แทนที่จะคอมไพเลอร์สร้างมันจากภาษาอื่น วิธีการนี้อาจเปลี่ยนแปลงได้กับทุกการอัพเดทคอมไพเลอร์
sbi

9
ในความเห็นต่ำต้อยของฉัน ... คุณใช้ C เมื่อคุณต้องการสำหรับฉัน: C นั้นง่ายกว่าและง่ายกว่าการใช้งานมากกว่า C ++ ... C ++ อาจดูเหมือน "C กับคลาส" แต่ตอนนี้ไม่ใช่ตอนนี้ ภาษาที่ซับซ้อนมากพร้อมด้วยสิ่งต่าง ๆ เช่น Virtual Constructors และ Templates
dysoco

คำตอบ:


184

คุณเลือก C เมื่อ

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

ในกรณีอื่น ๆ ทั้งหมดคุณควรเลือก C ++


15
ฉันยังจะเพิ่ม C + + ที่มีรุ่นตัวยกเว้นบางครั้งทำให้เกิดปัญหามากกว่าที่มันคุ้มค่าสำหรับการพูดเมล็ด OS อย่างน้อยนั่นคือความรู้สึกทั่วไปที่ฉันได้รับขณะอ่านเกี่ยวกับสิ่งของ
Coder

12
@SF: C เป็นภาษากลางหรือไม่ นั่นเป็นเรื่องใหม่ หรือค่อนข้างเก่ามาก บางทีถ้าคุณพูดคุยกับคนที่ไม่ได้เรียนรู้ภาษาใหม่ในช่วง 20 ปีที่ผ่านมา แต่ฉันจะบอกว่าความรู้ C นั้นไม่ธรรมดาอีกต่อไป
DeadMG

13
@SF: ตามที่ฉันเขียนที่อื่นฉันอยู่ในโครงการที่มีล้าน LoC และเห็น meta-stuff น้อยมากเมื่อเทียบกับโครงการ C ที่มีแฮ็คแมโคแฮ็กเกอร์ที่หลีกเลี่ยงไม่ได้และแพร่หลาย (OTOH ความสามารถในการสร้าง EDSL เมื่อจำเป็นอาจเป็นเครื่องมือที่ทรงพลังอย่างไม่น่าเชื่อในกล่องของคุณ) ส่วน C เป็นภาษากลาง: ฉันค่อนข้างจะยึดติดกับคำศัพท์ของฉันว่ามันเป็นตัวหารร่วมที่ต่ำที่สุด และฉันไม่ต้องการให้คนที่มีทักษะการเขียนโปรแกรมระดับปานกลางแฮ็คที่เคอร์เนลระบบปฏิบัติการ
sbi

18
@ Max: ฉันไม่เห็นด้วยอย่างสมบูรณ์ C เป็นภาษาที่ไร้ประโยชน์เว้นแต่บางอุปสรรคในทางปฏิบัติที่ผ่านไม่ได้ป้องกันการใช้ C ++
DeadMG

17
@ ปุ่ม: คุณเป็นคนที่อ้างสิทธิ์ ("C ++ ต้องการหน่วยความจำเพิ่ม") ดังนั้นคุณควรสำรองข้อมูลไว้ และไม่ฉันไม่ได้อ้างว่า C ++ ต้องการหน่วยความจำน้อยลง สิ่งที่ฉันพูดคือฟีเจอร์นี้มีค่าใช้จ่ายไม่ว่าคอมไพเลอร์จะนำไปใช้กับคุณ (ฟังก์ชั่นเสมือนจริง) หรือคุณทำมันเอง (อาเรย์ของตัวชี้ฟังก์ชั่น)
sbi

88

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

ฉันยังควรเพิ่มอย่างไรว่าจริงๆระบบเล็ก ๆ , C มีปัญหาว่าด้วยเหตุผลเดียวกันและภาษาประกอบเกือบจะเป็นทางเลือกที่เหมาะสมเท่านั้น ช่วงขนาดของระบบที่ C ใช้งานได้จริงมีขนาดค่อนข้างเล็กและหดตัวอย่างต่อเนื่อง (แม้ว่าฉันจะยอมรับช้าพอสมควร)

อีกครั้ง / เหตุผลในการใช้ C คือการจัดให้มีชุดฟังก์ชั่นที่คุณสามารถผูกจากภาษาอื่นใดเป็นหลัก คุณสามารถเขียนฟังก์ชั่นเหล่านี้ใน C ++ โดยกำหนดให้เป็นextern "C"ฟังก์ชั่นแต่การทำเช่นนั้นจะ จำกัด ฟังก์ชั่นเหล่านั้นเพื่อนำเสนอ "ใบหน้า" ของ C-life ไปสู่โลก - คลาส, ฟังก์ชันโอเวอร์โหลดเทมเพลตและฟังก์ชั่นสมาชิก ฯลฯ ใช้ สิ่งนี้ไม่ได้ จำกัด การพัฒนาไว้ที่ C เท่านั้น - มันสมเหตุสมผลอย่างสมบูรณ์ในการใช้คุณสมบัติ C ++ ใด ๆ และทุกอย่างภายในถ้าตราบใดที่อินเตอร์เฟสภายนอกดูเหมือนว่า C

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

เทมเพลตไม่ "แก้ไขปัญหาเกี่ยวกับระบบประเภทของภาษา" พวกเขาเพียงเพิ่มความสามารถพื้นฐานจำนวนมากที่ขาดหายไปเกือบทั้งหมดจาก C และ / หรือ C ++ โดยไม่มีเทมเพลต หนึ่งในเจตจำนงดั้งเดิมคือการจัดหาภาชนะที่ปลอดภัยสำหรับประเภท แต่ในความเป็นจริงพวกเขาไปไกลกว่านั้น

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

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


12
การสนับสนุนเครื่องมือไม่ใช่ควันสีแดง จริงอยู่ทุกวันนี้เรามีเสียงดัง แต่การสนับสนุนเครื่องมือสำหรับ C ++ นั้นช้ากว่าภาษาอื่นมากแม้ใน IDEs ที่ยิ่งใหญ่ ทำไมถึงเป็นอย่างนั้น? ง่ายเพราะจนกระทั่งเมื่อไม่นานมานี้ไม่มีเสียงดังกราว (และ GCC ก็ไม่ใช่ทางเลือก) จนกว่าจะถึงครึ่งปีที่แล้วหากคุณต้องการรหัส AST ของ C ++ คุณจะโชคไม่ดีหรือมีเงินหลายพันดอลลาร์ (ถ้าคุณซื้อส่วนหน้าของ EDG)
Konrad Rudolph

5
+1 และสำหรับบันทึกฉันมักเขียนรหัส C ++ สำหรับโปรเซสเซอร์ 8 บิตพร้อม 4KiB ROMs
avakar

2
+1 สำหรับคำตอบที่ยอดเยี่ยมโดยรวม สิ่งที่ฉันไม่เข้าใจ (ฉันไม่มีประสบการณ์ wrt. นี้) เป็นเหตุผล (ฉันเดาว่าเรากำลังพูดถึงการฝังตัว?) คอมไพเลอร์ C ควรผลิตรหัสปฏิบัติการขนาดเล็กกว่าคอมไพเลอร์ C ++ ที่ได้รับชุดคุณสมบัติเดียวกันที่ใช้ ? บางทีคุณอาจให้ข้อมูลอ้างอิงบางอย่าง
Martin Ba

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

3
"เราพบว่าการใช้ C ++ แทน C ทำให้ซอฟต์แวร์มีคุณภาพดีขึ้นและลดความพยายามในการบำรุงรักษา ... " ซึ่งเป็นข้อสรุปที่น่าจดจำ
Stephane Rolland

24

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

(หมายเหตุด้านข้าง: ลองดูคำวิจารณ์ของLinus Torvadsว่าทำไมเขาถึงชอบ C ถึง C ++ ฉันไม่จำเป็นต้องเห็นด้วยกับคะแนนของเขา แต่มันให้คุณเข้าใจว่าทำไมผู้คนถึงเลือก C มากกว่า C ++ แต่คนที่เห็นด้วยกับเขา อาจเลือก C เนื่องจากเหตุผลเหล่านี้)


51
-1สำหรับการพูดจาโผงผางของ Linus : - {
sbi

12
อย่าลบหนึ่งสำหรับฉันอย่างนั้น! ฮ่าฮ่า ฉันไม่เห็นด้วยกับ Linus แต่เป็นตัวอย่างที่ดีว่าทำไมคนถึงเลือก C มากกว่า C ++ (ถ้าพวกเขาเชื่อในสิ่งที่ Linus เชื่อ) ฉันไม่ได้แสดงความคิดเห็นเกี่ยวกับความถูกต้องของเหตุผลเหล่านั้น
Casey Patton

10
@CaseyPatton: โดยทั่วไปฉัน downvote ทุกคำตอบที่นำเสนอคำพูดจาโผงผางวาทศาสตร์นี้ไม่ใส่ร้ายราวกับว่ามันเป็นข้อโต้แย้งที่แท้จริง
sbi

11
@Coder: คุณไม่จำเป็นต้องรู้จักการใช้ STL เลย ประเด็นสำคัญของ STL ก็คือคุณไม่จำเป็นต้องรู้ถึงการนำไปปฏิบัติเว้นแต่ว่าคุณจะต้องพึ่งพาพฤติกรรมที่ไม่ได้กำหนดโดยมาตรฐานในกรณีนี้ทำไมต้องใช้ห้องสมุดมาตรฐาน? ยิ่งไปกว่านั้นมันเป็นมากกว่าเด็กบ้าที่ไม่ชอบภาษาเพราะพฤติกรรมของนักพัฒนา โปรแกรมเมอร์ C ทำตัวเหมือน C เป็นของขวัญจากพระเจ้าต่อมนุษย์และตาบอดเกินกว่าที่จะเห็นความจริงที่ชัดเจนว่า C ++ นำเสนอคุณลักษณะที่เป็นพื้นฐานและเหนือกว่า C โดยตรงอย่างแท้จริงเช่น RAII
DeadMG

8
@Coder: หากคุณจบลงด้วย shared_ptrs จำนวนมากไปยังวัตถุเดียวที่คุณล้นตัวนับภายในคุณกำลังทำผิด มาตรฐานจะระบุขนาดขั้นต่ำสำหรับเคาน์เตอร์ - อาจเป็น 32 บิตและมันค่อนข้างไม่สมจริงที่จะต้องมีมากกว่า 2 พันล้าน shared_ptrs กับวัตถุเดียว แม้ว่าวัตถุนั้นจะมีขนาด 0 และคุณมีตัวจัดสรรหน่วยความจำศูนย์ค่าโสหุ้ยแล้วคุณยังคงใช้หน่วยความจำ 16GB ของหน่วยความจำเพียงใน shared_ptrs
DeadMG

13

ปัญหาหลักที่ขาดหายไปจากคำตอบที่มีอยู่ (ณ เวลาที่โพสต์นี้) เป็นตัวเลือก

มันง่ายมาก ถ้าด้วยเหตุผลที่ไม่มีเหตุผลอย่างเต็มที่บางอย่างที่คุณรู้สึกว่าข้อยกเว้นที่จะไม่คุ้มค่าค่าใช้จ่ายแล้วคุณไม่ต้องใช้พวกเขา คุณยังสามารถมีเทมเพลตและ RAII และไลบรารี่มาตรฐานและไม่ต้องเขียน "throw" เพียงครั้งเดียว เช่นเดียวกับเทมเพลต ถ้าด้วยเหตุผลบางอย่างคุณรู้สึกว่าพวกเขาทำให้เกิดการยกเลิกไม่ได้ (และที่สำคัญจริง ๆ ซึ่งมันอยู่บนฝังตัวเท่านั้น) ปฎิบัติการจากนั้นก็แปลกใจ - คุณสามารถใช้โมฆะ * และขนาดของ (T) ได้ตลอดทั้งวัน ไม่มีอะไรบังคับให้คุณใช้คุณสมบัติ C ++ ใด ๆ เหนือ C

นั่นเป็นเหตุผลว่าทำไม C ++ จึงเป็นภาษาที่เหนือชั้นอย่างแท้จริง - คุณสามารถเลือกคุณสมบัติที่คุณต้องการและกลับไปที่การเขียนโปรแกรมแบบ C เมื่อคุณไม่ชอบคุณสมบัติที่กำหนด ดังนั้นเนื่องจาก C ++ เป็นทุกสิ่งที่ C เป็นและยิ่งกว่านั้นคือข้อเท็จจริงที่ชัดเจนว่า C ++ เป็นภาษาที่เหนือกว่า การแนะนำเป็นอย่างอื่นก็เหมือนกับพยายามแนะนำว่า 4 มากกว่า 5


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

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

1
@DeadMG: ตัวจัดสรรหมายถึงการรายงานข้อผิดพลาดโดยไม่ต้องส่งข้อยกเว้นอย่างไร นอกจากนี้การเพิ่มคุณสมบัติเพิ่มเติมไม่จำเป็นต้องดีกว่าเมื่อสิ่งที่มันทำคือเพิ่มความซับซ้อนหรือความซ้ำซ้อน
Mankarse

@Mankarse: หากคุณรวบรวมตัวเลือกเพื่อปิดการใช้งานข้อยกเว้นตัวจัดสรรอาจยกเลิกโปรแกรมหรือดำเนินการอย่างจริงจังเพื่อใช้ตัวชี้ null ขึ้นอยู่กับการใช้งานไลบรารี
Zan Lynx

4
@Mankarse: จากประสบการณ์ของฉันในปี 2550 เมื่อฉันลองใช้ระบบ Linux ที่มี RAM 1 GB และไม่มีการสับเปลี่ยนซอฟต์แวร์เดสก์ท็อปเกือบทั้งหมดจึงล้มเหลวในรูปแบบที่แย่มากเมื่อการจัดสรรหน่วยความจำล้มเหลวอยู่ดี
Zan Lynx

9

สิ่งที่เกี่ยวกับ C ++ ที่ทำให้โปรแกรมเมอร์ C เป็นกังวล

มีสิ่งมหัศจรรย์เกิดขึ้นมากมายภายใต้ประทุน คอนสตรัคเตอร์, destructors, เมธอดเสมือน, เท็มเพลต ฯลฯ สามารถสร้างรหัส C ++ ได้ง่ายและรวดเร็วกว่าการเขียนมากกว่ารหัส C เทียบเท่า แต่ยากที่จะเข้าใจและให้เหตุผลผ่าน สิ่งที่ง่ายเป็นFoo newFoo;อาจเรียกจำนวนมากของรหัสที่ขึ้นอยู่กับวิธีการสร้างการเรียนFoo(และชั้นเรียนใดก็ขึ้นอยู่กับ) ได้มีการกำหนด นี่คือเหตุผลที่การประชุมคือการเขียน++itแทนที่จะit++ทำซ้ำเมื่อผ่านตู้คอนเทนเนอร์เนื่องจาก postfix ++มักจะเกี่ยวข้องกับการดำเนินการคัดลอกที่มีราคาแพง

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

/* C version */
#include <stdio.h>
int main(void)
{
  char greeting[] = "Hello, world";
  printf("%s\n", greeting);
  return 0;
}
/* end C version */

/* C++ version */
#include <iostream>
#include <string>
int main(void)
{
  std::string greeting("Hello, world");
  std::cout << greeting << std::endl;
  return 0;
}
/* end C++ version */

พฤติกรรมเหมือนกันไม่แตกต่างกันมากทั้งในแง่ของแหล่งที่มา แต่ในกล่อง SLES 10 ฉันทำงานกับ gcc 4.1.2, อดีตสร้างปฏิบัติการของขนาด ~ 9kb ในขณะที่สองใช้เวลามากกว่า 12.5kb (ไม่มีการเพิ่มประสิทธิภาพ ) ใหญ่ขึ้นเกือบ 28% stringชนิดC ++ นั้นง่ายต่อการทำงานกับ IMO มากกว่า C string library และ C ++ ลำธารมีความยืดหยุ่นและปรับแต่งได้มากกว่า C stream แต่สำหรับโค้ดที่ใช้สมองเช่นนี้พวกเขาอาจไม่คุ้มกับค่าใช้จ่าย

C ++ เป็นภาษาที่มีขนาดใหญ่เมื่อเทียบกับ C โดยมีความหมายที่ซับซ้อนมาก ใช้เวลานานกว่าจะได้รับความเชี่ยวชาญกับ C ++ มากกว่า C ซึ่งหมายความว่าผู้คนจำนวนมากที่อ้างว่ารู้ C ++ ไม่รู้จักเช่นเดียวกับที่พวกเขาคิด

สิ่งที่เกี่ยวกับ C ที่ทำให้โปรแกรมเมอร์ C ++ เป็นกังวล

C ไม่ใช่ภาษาโปรแกรมที่ปลอดภัยด้วยจินตนาการ ไม่มีการตรวจสอบขอบเขตในอาร์เรย์ที่นำไปสู่พฤติกรรมที่เป็นประโยชน์มากมาย (ไม่ว่าจะเป็นผ่านgetsฟังก์ชั่นที่ตายแล้วหรือผ่านscanfกับตัวระบุ%sและ%[การแปลง) อย่างน้อย C ++ ให้คอนเทนเนอร์ที่คุณโยนข้อยกเว้นถ้าคุณพยายามเข้าถึงนอกช่วงที่กำหนดไว้ในปัจจุบัน C ทั้งหมดให้คุณคือ (หากคุณโชคดี) ละเมิดการแบ่งกลุ่ม

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

ในทำนองเดียวกันการจัดการข้อผิดพลาดใน C เป็นความเจ็บปวดในตูดเมื่อเทียบกับเครื่องมือ C ++ ให้ (กล่าวคือข้อยกเว้น) สิ่งที่สนุกจริงๆคือเมื่อคุณจัดสรรหน่วยความจำจำนวนมากแล้วเข้าสู่การประมวลผลของคุณ เมื่อคุณต้องถอยออกมาคุณจะต้องปล่อยหน่วยความจำนั้นตามลำดับที่ถูกต้อง ด้วยหลักการ C ++ และ RAII หลักการนี้ง่ายมากที่จะทำ

ดังนั้นเมื่อไหร่ฉันจะใช้อันหนึ่งมากกว่าอีกอัน?

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


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

9

Bjarne Stroustrup เก็บรักษารายการแอปพลิเคชันและ บริษัทที่ใช้ C ++; คุณสามารถโต้เถียงเกี่ยวกับขั้นตอนการเขียนโปรแกรมเทียบกับ OOP ทั้งหมดที่คุณต้องการ แต่คุณไม่สามารถโต้เถียงกับผลอุตสาหกรรมในช่วง 20 ปีที่ผ่านมา

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

ไลบรารีมาตรฐาน C ++ (STL) ในตัวเองมีเพียงเวกเตอร์และแผนที่เป็นเหตุผลเพียงพอที่จะใช้ C ++

C มักใช้สำหรับระบบฝังตัว

ฉันเองจะใช้ C เฉพาะในกรณีที่มีห้องสมุดบางแห่งที่มี C API


19
ประโยคสุดท้ายของคุณไม่ใช่เหตุผลที่จะใช้ C. คุณสามารถโทรหา C library จาก C ++
user207421

2
ฉันใช้ c ++ สำหรับโครงการ DSP ไม่ใช่ c
BЈовић

9

ฉันจะบอกว่าเหตุผลหลักที่ว่าทำไมฉันถึงเลือก C มากกว่า C ++ ก็ต่อเมื่อฉันต้องหันไปใช้ "สิ่งนี้มีเสถียรภาพ 1,000%" ของนาซ่า

C ++ คือ ~ 99% C เมื่อเราดูประสิทธิภาพและมันก็มีประสิทธิภาพมากกว่า ดังนั้นในขณะที่อยู่ใน C คุณสามารถเขียนโค้ดที่จะเร็วกว่า C ++ (คุณสามารถใช้ส่วนย่อยของ C ++ ได้โดยไม่มีข้อยกเว้น virtual, streaming, abstractions และอื่น ๆ แต่นั่นคือ C) เวลาในการปรับทุกอย่าง ในขณะที่ STL ได้รับการทดสอบและทำเช่นนั้นแล้วคุณจะเสียค่าใช้จ่ายมากกว่าประสิทธิภาพเล็กน้อยที่คุณอาจได้รับหรือเสียสละเพราะอัลกอริธึม STL เขียนโดยกลุ่มผู้เชี่ยวชาญและคุณอาจไม่ใช่ผู้เชี่ยวชาญในทุกสิ่ง

ในทางกลับกัน C ++ มี abstractions มากมาย เมื่ออยู่ภายใต้สถานการณ์ที่พวกเขารั่วไหลสิ่งนี้จะทำให้คุณเดือดร้อน และมีคนไม่กี่คนที่รู้ 100% ของ C ++ gotchas ในขณะที่ฉันเดาว่ามีอีกมากมายที่รู้จัก C gotchas ทั้งหมดดังนั้นการเขียนวิธีแก้ปัญหาที่สมาชิกในทีมทุกคนเข้าใจได้ง่ายขึ้นมากใน C

ตัวอย่าง: คุณรู้หรือไม่ว่าเมื่อshared_ptr<smthn>ใดที่จำนวนล้นอ้างอิงของจำนวนอ้างอิงนั้นจะเกิดข้อผิดพลาดขึ้นหรือไม่ สิ่งต่าง ๆ เหล่านี้ไม่เจ๋งเมื่อกระสวยกลับเข้าสู่บรรยากาศอย่างน้อยฉันก็เดาอย่างนั้น

นอกจากนี้การจัดการข้อยกเว้นนั้นยากมากเมื่อเทียบกับรหัสข้อผิดพลาด เป็นการยากที่จะดูว่าชั้นเรียนนั้นปลอดภัยยกเว้น 100% หรือไม่และรั่วได้ง่าย คนชั้นสูงหลายคนแสดงความคิดเห็นนี้


12
และวิธีการจัดการหน่วยความจำด้วยตนเองว่า "มีเสถียรภาพมากขึ้น" กว่า abstractions C ++ เหมือนstd::stringและชอบ? คุณเคยลองระบุแพลตฟอร์มที่shared_ptrมีตัวนับล้นหรือไม่? นั่นจะเป็นหนึ่งในแพลตฟอร์มตลก และถ้าคุณคิดว่าการจัดการข้อยกเว้นนั้นยากคุณควรดูรหัส C ที่ตรวจสอบข้อผิดพลาดที่เป็นไปได้ในการเรียกใช้ฟังก์ชันทุกครั้ง ฉันยอมรับ แต่นี่เป็นเพียงข้อโต้แย้งที่แข็งแกร่งยิ่งขึ้นต่อแถลงการณ์ของคุณ) ขออภัย แต่นี่เป็นสิ่งขับถ่ายวัวจริง ๆ
sbi

12
@Lundin: '"การใช้งานจะต้องมีความเสถียร 1,000%" ไม่อนุญาตให้มีการจัดสรรหน่วยความจำแบบไดนามิกตั้งแต่แรก' และอะไรทำให้คุณไม่ทำอย่างนั้นใน C ++? (และการทำงบผ้าห่มเกี่ยวกับความรู้และประสบการณ์ของผมมากกว่าการให้ข้อโต้แย้งใด ๆ ที่เป็นเคล็ดลับสำนวนราคาถูกค่อนข้าง.)
เอสบีไอ

10
@Lundin: ดีที่คุณได้เริ่มให้ข้อโต้แย้งมากกว่าวาทศาสตร์ แต่พวกเขาอ่อนแอ ว่าคุณมี "ลืม" หนึ่งในคุณสมบัติหลักของ C ++ (เทมเพลต), หนึ่งที่ทำให้รหัสปลอดภัยยิ่งขึ้น (เพราะมันช่วยให้อัลกอริทึมที่จะดำเนินการ - และดังนั้น, ล้มเหลว - ที่รวบรวม - เวลา , กำจัดข้อผิดพลาดรันไทม์), พูดเพื่อประโยชน์ของความรู้ภาษาที่คุณกำลังตัดสิน การลดภาษา C ++ เป็นภาษา OO ได้ถูกวิจารณ์ก่อนหน้านี้และด้วยเหตุผลที่ดี (นอกจากนี้คลาสที่มีการทำลายล้างแบบกำหนดค่าเป็นเครื่องมือที่ยอดเยี่ยมและเป็นประโยชน์สำหรับการจัดการทรัพยากรอื่น ๆ นอกเหนือจากหน่วยความจำ)
sbi

9
@Lundin แน่นอนคุณไม่ต้องการใช้std::stringหากคุณไม่ต้องการการจัดสรรแบบไดนามิก std::basic_string<char, std::char_traits<char>, some_allocator_here>คุณต้องการใช้
Luc Danton

10
@Coder: สิ่งที่คุณคิดว่าคุณพิสูจน์ด้วยสิ่งเหล่านี้? อันแรกคือโค้ดที่ไม่ดี (และจะเป็นข้อผิดพลาดในการรายงานที่ไม่ดีเท่ากับค่าส่งคืน) อันที่สองสร้างกรณีสำหรับRAII เกี่ยวกับการล้างข้อมูลด้วยตนเองซึ่ง C ++ dev ครึ่งตัวทุกคนจะเชียร์และ Joel เคารพเขาพูดบางสิ่งที่ฉันไม่เห็นด้วยอย่างยิ่ง ปลั๊กของเขาสำหรับการเข้า - ออกเดี่ยวครั้งเดียวนั้นส่งผลให้เกิดผายลมเก่าที่ไม่มีใครรู้จักซึ่งไม่เคยเห็นด้วยว่าสิ่งที่เขาเรียนรู้เมื่อ 25 ปีก่อนนั้นถูกค้นพบ (ใจคุณฉันได้รับการเขียนโปรแกรม 25 ปีที่ผ่านมาเมื่อ Sese เป็นรัฐของศิลปะ.)
เอสบีไอ

6

C เป็นชุดประกอบแบบพกพาที่มีไวยากรณ์ที่ดีกว่าทำให้โปรแกรมเมอร์สามารถควบคุมทุกอย่างได้อย่างเต็มที่

ในอีกทางหนึ่ง C ++ ทำสิ่งที่สนุกมาก (ฟังก์ชั่นเสมือนจริง, การบรรทุกเกินพิกัด, การแปลงอัตโนมัติ ฯลฯ ฯลฯ ) ซึ่งอาจไม่เป็นที่ต้องการเมื่อคุณต้องการให้แน่ใจว่าคุณ:

  • อย่าใช้หน่วยความจำมากกว่าที่คุณต้องการ
  • อย่าเข้าถึงหน้าหน่วยความจำโดยเจตนา (vtable สามารถใช้ได้ทุกที่)
  • อย่าเรียกใช้โค้ดมากเกินไปโดยไม่ตั้งใจ

และต้องการสิ่งที่ง่ายต่อการใช้งานจริง ๆ เพราะคุณให้ความสำคัญกับประสิทธิภาพ

มันไม่น่าประหลาดใจเลยและมันมีค่ามาก

หากคุณต้องการ (และฉันแนะนำ) อ่านแนวทางการเข้ารหัส JSF เกี่ยวกับสิ่งที่คุณต้องคิดเมื่อเขียน C ++ สำหรับการควบคุม avionics ทางทหาร มีกับดักมากมายที่คุณต้องระวังและมันอาจทำให้คุณติดขัด Bjarne เป็นส่วนหนึ่งของเอกสารนั้นดังนั้นเขาจึงรู้ว่ามันเกี่ยวกับอะไร

นอกจากนี้ C คอมไพล์เหมือนโทรลล์ที่ถูกไฟลวกโดนฟ้าผ่า C ++, OTOH อาจได้รับการสนับสนุนจากคนที่ลงทุนใน บริษัท SSD :)

(โดยส่วนตัวแล้วฉันชอบ C ++ มากกว่า แต่ฉันไม่ชอบ ...... เช่นกัน ;-P)


1
มีหลายสิ่งหลายอย่างที่ C ไม่สามารถควบคุมได้ ลองเขียนรหัสแบบพกพาที่มีประสิทธิภาพเพื่อทวีคูณ uint32_t ด้วย uint32_t เพื่อให้ได้ผลลัพธ์ uint32_t (ผลิตภัณฑ์ 32 บิตด้านล่าง) หากint64 บิตต้องมีตัวถูกดำเนินการอย่างน้อยหนึ่งตัวเพื่อuint64_tป้องกันพฤติกรรมที่ไม่ได้กำหนด แต่จะต้องส่งถึง 64 บิตเพื่อจุดประสงค์ในการคำนวณผลลัพธ์แบบ 32 บิตคือ - เพื่อทำให้มันอ่อน - "น่าประหลาดใจ"
supercat

มันไม่ใช่. คอมไพเลอร์ทำสิ่งต่าง ๆ เช่นการจัดสรรการลงทะเบียนให้คุณ ฉันไม่สามารถเขียนรหัสที่สามารถบำรุงรักษาได้ในชุดประกอบใน CI สามารถ
Nils

2

(เนื่องจากคุณมีความคุ้นเคยกับทั้งสองภาษาเท่ากัน)

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

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


1

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

ฉันเห็นภาษา C สมบูรณ์แบบใน 4 ด้าน: 1) ฉันคิดว่ามันเป็นภาษาที่ดีที่สุดที่จะใช้เมื่อเรียนรู้การเขียนโปรแกรมทุกประเภท [รวมกับการประกอบและความรู้เกี่ยวกับรหัสเครื่อง] 2) มันยอดเยี่ยมสำหรับการเขียนไดรเวอร์ 3) ซอฟต์แวร์และ 4) ซอฟต์แวร์ระบบในระดับต่ำสุด

C ++ เป็นภาษาเชิงวัตถุ แต่มันก็สามารถเป็นขั้นตอน (มากในทางของ C) หากคุณกำลังทำงานในโครงการขนาดใหญ่ซอฟต์แวร์ที่ใช้ GUI ซอฟต์แวร์เกมและซอฟต์แวร์ประเภทกราฟิกเข้มข้นอื่น ๆ ฉันก็จะพบว่า C ++, Java หรือแม้แต่ Objective-C เป็นตัวเลือกที่ดีที่สุดของคุณ อย่างไรก็ตามมีโปรแกรมบรรทัดคำสั่งหรือซอฟต์แวร์ระบบมากมายที่คุณอาจพบว่า C ++ นั้นดีหรือดีกว่า C


0

ในความคิดของฉันมีจุดหนึ่งหายไปในการสนทนานี้: มันง่ายกว่าใน C เพื่อให้อินเทอร์เฟซแบบไบนารีที่เสถียรจากไลบรารี ทั้งสำหรับการใช้งานกับภาษาอื่นเช่นเดียวกับ C ++

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

ฉันรู้ว่าทุกวันนี้คอมไพเลอร์มีสวิตช์เพื่อสร้างสิ่งที่เข้ากันได้กับ gcc แต่นั่นก็ไม่ได้ช่วยอะไรเสมอไป

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


0

C น่าจะเป็น C ++ ที่เหมาะสมกว่าเมื่อสร้างรหัส C (เช่นในการใช้ภาษาระดับสูงกว่า) ตัวอย่างเช่นมีคอมไพเลอร์เสียงกระเพื่อมเหมือนกันหลายตัวซึ่งปล่อยรหัส C (เช่นChicken , Scheme48 ... ) แต่ฉันรู้ว่าไม่มีใครเปล่งรหัส C ++ ของแท้ ( เครื่องมือMELTของฉันเปล่งรหัส C ++ แต่ฉันจะไม่เรียกรหัสนั้นว่าของแท้ รหัส C ++ ใช้คุณสมบัติ C ++ น้อยมาก)

รหัส C นั้นง่ายต่อการพิสูจน์แบบกึ่งอัตโนมัติ เครื่องมือวิเคราะห์แบบคงที่เช่นFrama-C (ซึ่งคุณใส่คำอธิบายประกอบรหัส C ของคุณด้วยความคิดเห็น ACSL เพื่อช่วยให้เหตุผลที่พิสูจน์ได้เกี่ยวกับรหัสของคุณ) มีให้สำหรับ C แต่ไม่มากสำหรับ C ++ 11 ที่สมบูรณ์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.