ไม่มีประโยชน์ที่ฉันสามารถนึกถึง (แต่ดูหมายเหตุของ JasonS ที่ด้านล่าง) รวมโค้ดหนึ่งบรรทัดเป็นฟังก์ชันหรือรูทีนย่อย ยกเว้นว่าคุณสามารถตั้งชื่อฟังก์ชั่นที่ "อ่านได้" แต่คุณสามารถแสดงความคิดเห็นในบรรทัดได้เช่นกัน และเนื่องจากการรวมบรรทัดของโค้ดไว้ในหน่วยความจำรหัสต้นทุนของฟังก์ชั่นพื้นที่สแต็คและเวลาดำเนินการดูเหมือนว่าสำหรับฉันแล้วว่าส่วนใหญ่จะต่อต้านได้ผล ในสถานการณ์การสอนหรือไม่? มันอาจทำให้รู้สึกบางอย่าง แต่ขึ้นอยู่กับชั้นเรียนของนักเรียนการเตรียมการล่วงหน้าหลักสูตรและอาจารย์ ส่วนใหญ่ฉันคิดว่ามันไม่ใช่ความคิดที่ดี แต่นั่นเป็นความคิดของฉัน
ซึ่งนำเราไปสู่จุดต่ำสุด พื้นที่คำถามกว้าง ๆ ของคุณเป็นเรื่องถกเถียงมานานหลายทศวรรษแล้วและยังคงเป็นประเด็นถกเถียงกันมาจนถึงทุกวันนี้ อย่างน้อยเมื่อฉันอ่านคำถามของคุณดูเหมือนว่าฉันจะเป็นคำถามที่อิงตามความคิดเห็น (ตามที่คุณถาม)
มันอาจถูกย้ายออกไปจากการเป็นความคิดเห็นตามที่เป็นถ้าคุณจะมีรายละเอียดเพิ่มเติมเกี่ยวกับสถานการณ์และอธิบายวัตถุประสงค์ที่คุณถือเป็นหลักอย่างระมัดระวัง ยิ่งคุณกำหนดเครื่องมือวัดของคุณได้ดีเท่าไหร่คำตอบก็จะยิ่งมากขึ้นเท่านั้น
พูดกว้าง ๆ คุณต้องการทำสิ่งต่อไปนี้สำหรับการเข้ารหัสใด ๆ (สำหรับด้านล่างฉันจะสมมติว่าเรากำลังเปรียบเทียบวิธีการต่าง ๆ ทั้งหมดซึ่งบรรลุเป้าหมายแน่นอนรหัสใด ๆ ที่ล้มเหลวในการทำงานที่ต้องการนั้นแย่กว่ารหัสที่ประสบความสำเร็จโดยไม่คำนึงถึงวิธีการเขียน)
- มีความสอดคล้องกับวิธีการของคุณเพื่อให้คนอื่นอ่านรหัสของคุณสามารถพัฒนาความเข้าใจว่าคุณเข้าใกล้กระบวนการเข้ารหัสของคุณอย่างไร การมีความไม่สอดคล้องกันอาจเป็นอาชญากรรมที่เลวร้ายที่สุด มันไม่เพียงทำให้คนอื่นยาก แต่มันทำให้มันยากสำหรับคุณที่จะกลับมาใช้รหัสในอีกหลายปีต่อมา
- ในระดับที่เป็นไปได้ให้ลองและจัดเรียงสิ่งต่าง ๆ เพื่อให้การเริ่มต้นของส่วนการทำงานต่างๆสามารถทำได้โดยไม่คำนึงถึงการสั่งซื้อ ในกรณีที่จำเป็นต้องมีการสั่งซื้อหากเป็นเพราะการมีเพศสัมพันธ์อย่างใกล้ชิดของฟังก์ชั่นย่อยที่เกี่ยวข้องอย่างสูงสองรายการให้พิจารณาการกำหนดค่าเริ่มต้นครั้งเดียวสำหรับทั้งคู่เพื่อให้สามารถเรียงลำดับใหม่ได้โดยไม่ทำให้เกิดอันตราย หากไม่สามารถทำได้ให้จัดทำเอกสารข้อกำหนดการเริ่มต้นการสั่งซื้อ
- ห่อหุ้มความรู้ในที่เดียวหากเป็นไปได้ ค่าคงที่ไม่ควรซ้ำซ้อนกันทุกจุดในรหัส สมการที่แก้สำหรับตัวแปรบางตัวควรมีอยู่ในที่เดียวและที่เดียว และอื่น ๆ หากคุณพบว่าตัวเองกำลังคัดลอกและวางเส้นบางชุดที่มีพฤติกรรมที่ต้องการในสถานที่ที่หลากหลายลองพิจารณาวิธีการที่จะรวบรวมความรู้นั้นไว้ในที่เดียวและใช้งานได้ตามที่ต้องการ ตัวอย่างเช่นถ้าคุณมีโครงสร้างที่ต้องเดินในทางที่เฉพาะเจาะจงให้ทำไม่ได้ทำซ้ำรหัส tree-walking ในทุก ๆ ที่ที่คุณต้องการวนซ้ำโหนดของต้นไม้ ให้จับวิธีการเดินต้นไม้ในที่เดียวและใช้แทน ด้วยวิธีนี้หากต้นไม้เปลี่ยนไปและวิธีการเดินเปลี่ยนไปคุณมีที่เดียวเท่านั้นที่ต้องกังวลและรหัสที่เหลือทั้งหมด "ทำงานได้ถูกต้อง"
- หากคุณกระจายกิจวัตรประจำวันของคุณไปยังกระดาษแผ่นใหญ่ที่มีลูกศรเชื่อมต่อพวกเขาตามที่ถูกเรียกโดยกิจวัตรอื่น ๆ คุณจะเห็นในแอปพลิเคชันใด ๆ จะมี "กลุ่ม" ของกิจวัตรที่มีลูกศรจำนวนมาก ระหว่างตัวเอง แต่มีลูกศรเพียงไม่กี่ตัวนอกกลุ่ม ดังนั้นจะมีขอบเขตตามธรรมชาติของรูทีนคู่ที่ใกล้ชิดและการเชื่อมต่อคู่อย่างหลวม ๆ ระหว่างกลุ่มอื่น ๆ ใช้ข้อเท็จจริงนี้เพื่อจัดระเบียบโค้ดของคุณเป็นโมดูล สิ่งนี้จะจำกัดความซับซ้อนของรหัสของคุณอย่างชัดเจน
ข้างต้นเป็นจริงโดยทั่วไปเกี่ยวกับการเข้ารหัสทั้งหมด ฉันไม่ได้พูดคุยเกี่ยวกับการใช้พารามิเตอร์ตัวแปรท้องถิ่นหรือตัวแปรโกลบอลแบบคงที่ ฯลฯ เหตุผลก็คือสำหรับการเขียนโปรแกรมแบบฝังพื้นที่แอพพลิเคชันมักจะมีข้อ จำกัด ใหม่ที่รุนแรงและมีความสำคัญมากและเป็นไปไม่ได้ที่จะพูดถึงพวกมันทั้งหมด และนั่นไม่ได้เกิดขึ้นที่นี่อย่างไรก็ตาม
ข้อ จำกัด เหล่านี้อาจมี (และมากกว่า) ของสิ่งเหล่านี้:
- ข้อ จำกัด ด้านต้นทุนที่รุนแรงต้องใช้ MCU แบบดั้งเดิมที่มี RAM ขนาดเล็กและแทบไม่มีการนับพิน I / O สำหรับสิ่งเหล่านี้จะใช้กฎชุดใหม่ทั้งหมด ตัวอย่างเช่นคุณอาจต้องเขียนในรหัสการชุมนุมเพราะมีพื้นที่รหัสไม่มาก คุณอาจต้องใช้ตัวแปรแบบคงที่เท่านั้นเนื่องจากการใช้ตัวแปรท้องถิ่นมีค่าใช้จ่ายสูงและใช้เวลานานเกินไป คุณอาจต้องหลีกเลี่ยงการใช้รูทีนย่อยมากเกินไปเพราะ (เช่นชิ้นส่วน Microchip PIC บางส่วน) มีการลงทะเบียนฮาร์ดแวร์เพียง 4 รายการเท่านั้นเพื่อจัดเก็บที่อยู่ส่งคืนของรูทีนย่อย ดังนั้นคุณอาจต้อง "บี้" รหัสของคุณอย่างมาก เป็นต้น
- ข้อ จำกัด ด้านพลังงานที่รุนแรงต้องใช้รหัสที่ออกแบบมาอย่างระมัดระวังเพื่อเริ่มและปิดส่วนใหญ่ของ MCU และวางข้อ จำกัด ที่รุนแรงเกี่ยวกับเวลาดำเนินการของรหัสเมื่อทำงานด้วยความเร็วเต็ม อีกครั้งนี้อาจต้องมีการเข้ารหัสประกอบบางครั้ง
- ความต้องการเวลาที่รุนแรง ตัวอย่างเช่นมีบางครั้งที่ฉันต้องแน่ใจว่าการส่งสัญญาณของ open-drain 0 นั้นต้องใช้จำนวนรอบที่เท่ากันกับการส่งของ 1 และการสุ่มตัวอย่างที่บรรทัดเดียวกันนี้ก็ต้องดำเนินการด้วย ด้วยระยะสัมพัทธ์ที่แน่นอนกับเวลานี้ นี่หมายความว่า C ไม่สามารถใช้ที่นี่ได้ วิธีเดียวที่เป็นไปได้ในการรับประกันนั้นคือการสร้างรหัสชุดประกอบอย่างระมัดระวัง (และถึงแม้จะไม่ใช่ทุกการออกแบบของ ALU)
และอื่น ๆ (รหัสการเดินสายสำหรับเครื่องมือทางการแพทย์ที่มีความสำคัญต่อชีวิตนั้นมีทั้งโลกด้วยเช่นกัน)
ผลที่สุดของที่นี่คือการเข้ารหัสที่ฝังตัวมักจะไม่ใช่ของฟรีสำหรับทุกคนที่คุณสามารถเขียนโค้ดได้เหมือนในเวิร์กสเตชัน มักจะมีเหตุผลที่รุนแรงและมีการแข่งขันสำหรับข้อ จำกัด ที่ยากมากหลากหลายรูปแบบ และสิ่งเหล่านี้อาจโต้เถียงกับคำตอบแบบดั้งเดิมและหุ้น
เกี่ยวกับความสามารถในการอ่านฉันพบว่ารหัสนั้นสามารถอ่านได้ถ้ามันถูกเขียนในลักษณะที่สอดคล้องกันซึ่งฉันสามารถเรียนรู้ได้ในขณะที่ฉันอ่าน และในกรณีที่ไม่มีความพยายามที่จะทำให้งงงวยรหัส ไม่จำเป็นต้องมีอีกแล้ว
รหัสที่อ่านได้นั้นค่อนข้างมีประสิทธิภาพและสามารถตอบสนองความต้องการด้านบนทั้งหมดที่ฉันได้กล่าวไปแล้ว สิ่งสำคัญคือคุณต้องเข้าใจอย่างถ่องแท้ว่าแต่ละบรรทัดของโค้ดที่คุณเขียนนั้นสร้างขึ้นที่แอสเซมบลีหรือระดับเครื่องในขณะที่คุณเขียนมัน C ++ วางภาระที่ร้ายแรงในโปรแกรมเมอร์ที่นี่เพราะมีหลายสถานการณ์ที่โค้ดตัวอย่างของรหัส C ++ ที่เหมือนกันจะสร้างโค้ดโค้ดที่แตกต่างกันของเครื่องที่มีประสิทธิภาพแตกต่างกันอย่างมากมาย แต่โดยทั่วไป C มักเป็นภาษา "สิ่งที่คุณเห็นคือสิ่งที่คุณได้รับ" ดังนั้นจึงปลอดภัยกว่าในเรื่องนั้น
แก้ไขโดย JasonS:
ฉันใช้ C มาตั้งแต่ปี 1978 และ C ++ ตั้งแต่ประมาณปี 1987 และฉันมีประสบการณ์มากมายในการใช้ทั้งสำหรับเมนเฟรมคอมพิวเตอร์มินิคอมพิวเตอร์และแอปพลิเคชั่นฝังตัว
Jason แสดงความคิดเห็นเกี่ยวกับการใช้ 'inline' เป็นตัวดัดแปลง (ในมุมมองของฉันนี่เป็นความสามารถที่ค่อนข้าง "ใหม่" เพราะมันไม่ได้มีอยู่เพียงครึ่งชีวิตของฉันหรือมากกว่าโดยใช้ C และ C ++) การใช้ฟังก์ชั่นอินไลน์สามารถโทรออกได้จริง ๆ (แม้แต่บรรทัดเดียว รหัส) ค่อนข้างใช้งานได้จริง และจะดีกว่าถ้าเป็นไปได้มากกว่าการใช้มาโครเนื่องจากการพิมพ์ที่คอมไพเลอร์สามารถใช้ได้
แต่ก็มีข้อ จำกัด เช่นกัน อย่างแรกคือคุณไม่สามารถพึ่งพาคอมไพเลอร์เพื่อ "รับคำใบ้" อาจหรือไม่ก็ได้ และมีเหตุผลที่ดีที่จะไม่ใช้คำใบ้ (สำหรับตัวอย่างที่ชัดเจนหากที่อยู่ของฟังก์ชั่นนี้ต้องใช้อินสแตนซ์ของฟังก์ชั่นและการใช้ที่อยู่ในการโทรจะ ... ต้องมีการโทรรหัสไม่สามารถ inlined แล้ว) มี เหตุผลอื่นเช่นกัน คอมไพเลอร์อาจมีเกณฑ์ที่หลากหลายซึ่งพวกเขาตัดสินว่าจะจัดการกับคำใบ้ได้อย่างไร และในฐานะโปรแกรมเมอร์หมายความว่าคุณต้องใช้เวลาเรียนรู้เกี่ยวกับแง่มุมของคอมไพเลอร์มิฉะนั้นคุณอาจตัดสินใจด้วยความคิดที่ไม่สมบูรณ์ ดังนั้นจึงเป็นการเพิ่มภาระให้กับผู้เขียนโค้ดและผู้อ่านทุกคนและทุกคนที่วางแผนที่จะย้ายรหัสไปยังคอมไพเลอร์อื่น ๆ เช่นกัน
นอกจากนี้คอมไพเลอร์ C และ C ++ ยังรองรับการคอมไพล์แยกต่างหาก ซึ่งหมายความว่าพวกเขาสามารถรวบรวมรหัส C หรือ C ++ หนึ่งชิ้นโดยไม่ต้องรวบรวมรหัสอื่นที่เกี่ยวข้องสำหรับโครงการ เพื่อให้โค้ดแบบอินไลน์สมมติว่าคอมไพเลอร์อาจเลือกที่จะทำเช่นนั้นไม่เพียง แต่ต้องมีการประกาศ "ในขอบเขต" แต่ต้องมีคำจำกัดความด้วยเช่นกัน โดยปกติโปรแกรมเมอร์จะทำงานเพื่อให้แน่ใจว่าเป็นกรณีนี้หากใช้ 'อินไลน์' แต่มันง่ายสำหรับความผิดพลาดที่จะคืบเข้ามา
โดยทั่วไปแล้วในขณะที่ฉันใช้อินไลน์ด้วยซึ่งฉันคิดว่ามันเหมาะสมฉันมักจะคิดว่าฉันไม่สามารถวางใจได้ หากประสิทธิภาพเป็นข้อกำหนดที่สำคัญและฉันคิดว่า OP ได้เขียนไว้อย่างชัดเจนแล้วว่ามีผลการปฏิบัติงานที่สำคัญเมื่อพวกเขาไปสู่เส้นทางที่มีการใช้งานมากขึ้นฉันจะเลือกหลีกเลี่ยงการใช้อินไลน์เป็นแนวทางในการเข้ารหัสและ จะทำตามรูปแบบการเขียนที่ต่างกันเล็กน้อย แต่สอดคล้องกันทั้งหมด
หมายเหตุสุดท้ายเกี่ยวกับ 'อินไลน์' และคำจำกัดความว่า "อยู่ในขอบเขต" สำหรับขั้นตอนการรวบรวมแยกต่างหาก เป็นไปได้ (ไม่น่าเชื่อถือเสมอไป) สำหรับงานที่ต้องดำเนินการในขั้นตอนการเชื่อมโยง สิ่งนี้สามารถเกิดขึ้นได้หากคอมไพเลอร์ C / C ++ ฝังรายละเอียดเพียงพอในไฟล์วัตถุเพื่อให้ตัวเชื่อมโยงดำเนินการตามคำขอ 'อินไลน์' โดยส่วนตัวฉันไม่ได้พบกับระบบเชื่อมโยง (นอก Microsoft) ที่รองรับความสามารถนี้ แต่มันสามารถเกิดขึ้นได้ อีกครั้งว่าควรจะพึ่งพาหรือไม่นั้นขึ้นอยู่กับสถานการณ์ แต่ฉันมักจะคิดว่าสิ่งนี้ไม่ได้ถูกโกยเข้ากับลิงเกอร์เว้นแต่ฉันจะรู้ว่ามีหลักฐานที่ดี และถ้าฉันพึ่งพามันมันจะถูกบันทึกไว้ในสถานที่ที่โดดเด่น
C ++
สำหรับผู้ที่สนใจนี่เป็นตัวอย่างว่าทำไมฉันถึงยังคงระมัดระวัง C ++ อย่างต่อเนื่องเมื่อทำการเข้ารหัสแอพพลิเคชั่นที่ฝังตัวไว้ ฉันจะโยนคำศัพท์บางคำที่ฉันคิดว่าโปรแกรมเมอร์ C ++ ที่ฝังตัวทั้งหมดจำเป็นต้องรู้จักความเย็น :
- ความเชี่ยวชาญเทมเพลตบางส่วน
- vtables
- วัตถุฐานเสมือน
- กรอบการเปิดใช้งาน
- กรอบการเปิดใช้งานผ่อนคลาย
- การใช้พอยน์เตอร์อัจฉริยะในตัวสร้างและทำไม
- การเพิ่มประสิทธิภาพของค่าตอบแทน
นั่นเป็นเพียงรายการสั้น ๆ หากคุณยังไม่ได้รู้ทุกอย่างเกี่ยวกับข้อกำหนดเหล่านั้นและทำไมฉันจึงระบุพวกเขา (และอีกมากมายที่ฉันไม่ได้อยู่ในรายการที่นี่) จากนั้นฉันจะแนะนำให้ใช้ C ++ สำหรับงานฝังตัวเว้นแต่จะไม่มีตัวเลือกสำหรับโครงการ .
ลองมาดูที่ความหมายของ C ++ ข้อยกเว้นเพื่อรับรสชาติ
คอมไพเลอร์ C ++ จะต้องสร้างรหัสที่ถูกต้องสำหรับหน่วยการคอมไพล์เมื่อไม่ทราบว่าต้องใช้การจัดการข้อยกเว้นชนิดใดในหน่วยการคอมไพล์แยกคอมไพล์แยกต่างหากและในเวลาอื่น BAB
ใช้รหัสลำดับนี้ซึ่งเป็นส่วนหนึ่งของฟังก์ชั่นบางอย่างในหน่วยการคอมไพล์ :A
.
.
foo ();
String s;
foo ();
.
.
เพื่อวัตถุประสงค์ในการอภิปรายรวบรวมหน่วยไม่ได้ใช้ 'try..catch' ได้ทุกที่ในแหล่งที่มาของ มันไม่ใช้ 'โยน' ในความเป็นจริงสมมติว่ามันไม่ได้ใช้แหล่งข้อมูลใด ๆ ที่ไม่สามารถคอมไพล์ด้วยคอมไพเลอร์ C ยกเว้นความจริงที่ว่ามันใช้การสนับสนุนไลบรารี C ++ และสามารถจัดการวัตถุเช่นสตริง รหัสนี้อาจเป็นไฟล์รหัสต้นฉบับ C ที่ได้รับการแก้ไขเล็กน้อยเพื่อใช้ประโยชน์จากคุณลักษณะบางอย่างของ C ++ เช่นคลาส StringA
นอกจากนี้สมมติว่า foo () เป็นโพรซีเดอร์ภายนอกที่ตั้งอยู่ในคอมไพล์ยูนิตและคอมไพเลอร์มีการประกาศสำหรับมัน แต่ไม่ทราบคำจำกัดความของมันB
คอมไพเลอร์ C ++ เห็นการเรียกครั้งแรกเพื่อ foo () และสามารถอนุญาตให้เฟรมการเปิดใช้งานปกติคลายลงหาก foo () ส่งข้อยกเว้น กล่าวอีกนัยหนึ่งคอมไพเลอร์ C ++ รู้ดีว่าไม่จำเป็นต้องมีโค้ดพิเศษในตอนนี้เพื่อสนับสนุนกระบวนการคลายเฟรมที่เกี่ยวข้องกับการจัดการข้อยกเว้น
แต่เมื่อมีการสร้างสตริง s คอมไพเลอร์ C ++ จะรู้ว่าต้องถูกทำลายอย่างถูกต้องก่อนที่เฟรมการผ่อนคลายจะได้รับอนุญาตหากมีข้อยกเว้นเกิดขึ้นในภายหลัง ดังนั้นการเรียกครั้งที่สองไปที่ foo () จึงแตกต่างจากความหมายแรก หากการเรียกครั้งที่สองไปยัง foo () ส่งข้อยกเว้น (ซึ่งอาจหรือไม่อาจทำได้) คอมไพเลอร์จะต้องวางโค้ดที่ออกแบบมาเพื่อจัดการกับการทำลายของ String s ก่อนที่จะอนุญาตให้เฟรมปกติคลายลง สิ่งนี้แตกต่างจากรหัสที่จำเป็นสำหรับการโทรครั้งแรกเพื่อ foo ()
(เป็นไปได้ที่จะเพิ่มการตกแต่งเพิ่มเติมใน C ++ เพื่อช่วย จำกัด ปัญหานี้ แต่ความจริงก็คือโปรแกรมเมอร์ที่ใช้ C ++ จะต้องตระหนักถึงผลกระทบของแต่ละบรรทัดของรหัสที่เขียน)
ซึ่งแตกต่างจาก malloc ของ C, C ++ ใหม่ใช้ข้อยกเว้นในการส่งสัญญาณเมื่อไม่สามารถทำการจัดสรรหน่วยความจำแบบดิบได้ ดังนั้นจะ 'dynamic_cast' (ดูที่ Stroustrup ของภาษาที่ 3, ภาษา C ++ Programming, หน้า 384 และ 385 สำหรับข้อยกเว้นมาตรฐานใน C ++.) คอมไพเลอร์อาจอนุญาตให้พฤติกรรมนี้ถูกปิดใช้งาน แต่โดยทั่วไปคุณจะต้องเสียค่าโสหุ้ยเนื่องจากข้อยกเว้นที่เกิดขึ้นอย่างถูกต้องในการจัดการอารัมภบทและ epilogues ในรหัสที่สร้างขึ้นแม้ว่าข้อยกเว้นที่เกิดขึ้นจริงไม่ได้เกิดขึ้นและแม้ในขณะที่ฟังก์ชั่นการรวบรวมไม่ได้มีบล็อกการจัดการข้อยกเว้น (Stroustrup ได้คร่ำครวญเรื่องนี้ต่อสาธารณะ)
หากไม่มีเทมเพลตเฉพาะบางส่วน (ไม่ใช่คอมไพเลอร์ C ++ ทั้งหมดที่สนับสนุน) การใช้เทมเพลตสามารถสะกดความหายนะสำหรับการเขียนโปรแกรมฝังตัว ถ้าไม่มีมันก็จะเป็นการเสี่ยงที่ร้ายแรงซึ่งอาจทำให้โครงการหน่วยความจำขนาดเล็กฝังตัวในแฟลชได้
เมื่อฟังก์ชัน C ++ คืนค่าวัตถุคอมไพเลอร์ที่ไม่มีชื่อจะถูกสร้างและทำลาย คอมไพเลอร์ C ++ บางตัวสามารถให้รหัสที่มีประสิทธิภาพหากตัวสร้างวัตถุถูกนำมาใช้ในคำสั่งส่งคืนแทนที่จะเป็นวัตถุในท้องถิ่นลดความต้องการการก่อสร้างและการทำลายโดยวัตถุหนึ่ง แต่ไม่ใช่ว่าคอมไพเลอร์ทุกคนจะทำสิ่งนี้และโปรแกรมเมอร์ C ++ หลายคนก็ไม่ทราบด้วยซ้ำว่า
การให้ตัวสร้างออบเจ็กต์ด้วยพารามิเตอร์ชนิดเดียวอาจอนุญาตให้คอมไพเลอร์ C ++ ค้นหาเส้นทางการแปลงระหว่างสองประเภทด้วยวิธีที่ไม่คาดคิดอย่างสมบูรณ์สำหรับโปรแกรมเมอร์ พฤติกรรม "ฉลาด" แบบนี้ไม่ได้เป็นส่วนหนึ่งของ C
ประโยค catch ที่ระบุชนิดของฐานจะ "slice" เป็นวัตถุที่ถูกส่งออกมาเนื่องจากวัตถุที่ส่งออกมาถูกคัดลอกโดยใช้ "ชนิดคงที่" ของ catch clause และไม่ใช่ชนิดไดนามิกของวัตถุ แหล่งที่มาของข้อยกเว้นความทุกข์ยากไม่ใช่เรื่องแปลก (เมื่อคุณรู้สึกว่าคุณสามารถจ่ายได้ยกเว้นในรหัสฝังตัวของคุณ)
คอมไพเลอร์ C ++ สามารถสร้าง constructors, destructors, copy constructors และโอเปอเรเตอร์การมอบหมายสำหรับคุณโดยอัตโนมัติด้วยผลลัพธ์ที่ไม่ได้ตั้งใจ ต้องใช้เวลาในการรับความสะดวกด้วยรายละเอียดของสิ่งนี้
ผ่านอาร์เรย์ของวัตถุที่ได้รับไปยังฟังก์ชั่นการยอมรับอาร์เรย์ของวัตถุฐานไม่ค่อยสร้างคำเตือนคอมไพเลอร์ แต่มักจะก่อให้เกิดพฤติกรรมที่ไม่ถูกต้อง
เนื่องจาก C ++ ไม่เรียกใช้ตัวทำลายของวัตถุที่สร้างขึ้นบางส่วนเมื่อมีข้อยกเว้นเกิดขึ้นในตัวสร้างวัตถุการจัดการข้อยกเว้นในตัวสร้างมักจะเรียกว่า "ตัวชี้อัจฉริยะ" เพื่อรับรองว่าชิ้นส่วนที่สร้างในตัวสร้างจะถูกทำลายอย่างถูกต้อง . (ดู Stroustrup, หน้า 367 และ 368) นี่เป็นปัญหาทั่วไปในการเขียนคลาสที่ดีใน C ++ แต่แน่นอนว่าหลีกเลี่ยงใน C เนื่องจาก C ไม่มีความหมายของการก่อสร้างและการทำลายในตัวการเขียนรหัสที่เหมาะสมเพื่อจัดการการก่อสร้าง ของ subobjects ภายในวัตถุหมายถึงการเขียนรหัสที่ต้องรับมือกับปัญหาความหมายเฉพาะใน C ++; ในคำอื่น ๆ "เขียนรอบ" พฤติกรรมความหมาย C ++
C ++ อาจคัดลอกวัตถุที่ส่งไปยังพารามิเตอร์ของวัตถุ ตัวอย่างเช่นในแฟรกเมนต์ต่อไปนี้การเรียก "rA (x);" อาจทำให้คอมไพเลอร์ C ++ สามารถเรียกใช้ Constructor สำหรับพารามิเตอร์ p เพื่อที่จะเรียกใช้ตัวสร้างการคัดลอกเพื่อถ่ายโอนวัตถุ x ไปยังพารามิเตอร์ p จากนั้นตัวสร้างอื่นสำหรับวัตถุส่งคืน (ไม่มีชื่อชั่วคราว) ของฟังก์ชัน rA ซึ่งแน่นอนคือ คัดลอกจากพารามิเตอร์ p ที่แย่กว่านั้นถ้าคลาส A มีวัตถุของตัวเองซึ่งต้องการการก่อสร้างสิ่งนี้สามารถทำให้กล้องโทรทรรศน์ทรุดโทรมได้ (โปรแกรมเมอร์ AC จะหลีกเลี่ยงขยะนี้ส่วนใหญ่เพิ่มประสิทธิภาพด้วยมือเนื่องจากโปรแกรมเมอร์ C ไม่มีไวยากรณ์ที่มีประโยชน์และต้องแสดงรายละเอียดทั้งหมดทีละรายการ)
class A {...};
A rA (A p) { return p; }
// .....
{ A x; rA(x); }
ในที่สุดโน้ตย่อสำหรับโปรแกรมเมอร์ C longjmp () ไม่มีพฤติกรรมแบบพกพาใน C ++ (โปรแกรมเมอร์ C บางคนใช้สิ่งนี้เป็นกลไก "ยกเว้น") คอมไพเลอร์ C ++ บางคนจะพยายามตั้งค่าสิ่งต่างๆเพื่อล้างข้อมูลเมื่อใช้ longjmp แต่พฤติกรรมนั้นไม่ได้พกพาใน C ++ ถ้าคอมไพเลอร์ทำความสะอาดวัตถุที่สร้างขึ้นมันไม่ใช่แบบพกพา หากคอมไพเลอร์ไม่ได้ล้างพวกเขาแล้ววัตถุจะไม่ถูกทำลายถ้ารหัสออกจากขอบเขตของวัตถุที่สร้างขึ้นเป็นผลมาจาก longjmp และพฤติกรรมที่ไม่ถูกต้อง (หากการใช้ longjmp ใน foo () ไม่ออกจากขอบเขตพฤติกรรมอาจไม่ปกติ) สิ่งนี้ไม่ได้ใช้บ่อยเกินไปโดยโปรแกรมเมอร์ C ที่ฝังตัว แต่ควรทำให้พวกเขาตระหนักถึงปัญหาเหล่านี้ก่อนที่จะใช้พวกเขา