การใช้คอมไพเลอร์ C ++ เป็นเพียงการปฏิบัติที่เกินความจำเป็นหรือไม่
จุดยืนของ IMHO คือใช่และฉันจะต้องกลายเป็นโรคจิตเภทเพื่อตอบคำถามนี้เพราะฉันรักทั้งสองภาษา แต่มันไม่มีอะไรเกี่ยวข้องกับประสิทธิภาพ แต่อย่างเช่นความปลอดภัยและการใช้ภาษาที่ใช้สำนวน
ซีไซด์
จากจุดยืนของ C ฉันพบว่ามันสิ้นเปลืองมากที่จะทำให้โค้ดของคุณต้องการ C ++ เพียงเพื่อใช้ฟังก์ชันโอเวอร์โหลด นอกจากว่าคุณจะใช้มันเพื่อความหลากหลายแบบคงที่ด้วยเทมเพลต C ++ มันเป็นเรื่องเล็ก ๆ น้อย ๆ ที่ได้มาจากการแลกเปลี่ยนกับการสร้างประโยคภาษาน้ำตาลสลับกับภาษาที่แตกต่างไปจากเดิมอย่างสิ้นเชิง นอกจากนี้หากคุณต้องการส่งออกฟังก์ชั่นของคุณไปยัง dylib (อาจเป็นหรือเป็นปัญหาที่ไม่ได้เกิดขึ้นจริง) คุณจะไม่สามารถทำเช่นนั้นได้อีกต่อไปเพื่อการบริโภคอย่างกว้างขวางด้วยสัญลักษณ์ชื่อที่มีชื่อเป็นภาษาต่างๆ
C ++ ด้านข้าง
จากมุมมอง C ++ คุณไม่ควรใช้ C ++ เช่น C ที่มีฟังก์ชั่นโหลดมากเกินไป นี่ไม่ใช่การหยิ่งยโสโวหาร แต่เกี่ยวข้องกับการใช้งานจริงของ C ++ ทุกวัน
ชนิดปกติของคุณรหัส C เป็นเพียงมีเหตุผลมีสติและ "ปลอดภัย" ในการเขียนถ้าคุณทำงานกับระบบการพิมพ์ C structs
ที่ห้ามสิ่งที่ต้องการใน เมื่อคุณทำงานในระบบที่สมบูรณ์ยิ่งขึ้นของ C ++ ฟังก์ชั่นประจำวันที่มีมูลค่ามหาศาลเช่นmemset
และmemcpy
ไม่กลายเป็นฟังก์ชั่นที่คุณควรพึ่งพาตลอดเวลา แต่โดยทั่วไปแล้วฟังก์ชั่นเหล่านี้เป็นฟังก์ชั่นที่คุณต้องการหลีกเลี่ยงเช่นโรคระบาดเนื่องจากด้วยประเภท C ++ คุณไม่ควรปฏิบัติต่อมันเช่นบิตบิตและไบต์ที่จะคัดลอกและสับไปมาและเป็นอิสระ แม้ว่ารหัสของคุณจะใช้สิ่งต่าง ๆ เช่นmemset
บนพื้นฐานและ POD UDT เท่านั้นในขณะนี้ทุกคนจะเพิ่ม ctor ลงใน UDT ใด ๆ ที่คุณใช้ (รวมถึงเพียงแค่เพิ่มสมาชิกที่ต้องการหนึ่งอย่างเช่นstd::unique_ptr
สมาชิก) กับฟังก์ชั่นดังกล่าวหรือฟังก์ชั่นเสมือนจริงหรืออะไรก็ตามที่จัดเรียงมันทำให้การเข้ารหัส C-style ปกติของคุณไวต่อพฤติกรรมที่ไม่ได้กำหนด นำติดตัวไปจาก Herb Sutter
memcpy
และmemcmp
ละเมิดระบบพิมพ์ การใช้memcpy
เพื่อคัดลอกวัตถุก็เหมือนกับการทำเงินโดยใช้เครื่องถ่ายเอกสาร การใช้memcmp
เพื่อเปรียบเทียบวัตถุก็เหมือนกับการเปรียบเทียบเสือดาวโดยนับจำนวนจุดของพวกมัน เครื่องมือและวิธีการอาจดูเหมือนว่าจะทำงาน แต่พวกเขาหยาบเกินไปที่จะยอมรับได้ วัตถุ C ++ นั้นเกี่ยวกับการซ่อนข้อมูล (ซึ่งเป็นหลักการที่ให้ผลกำไรสูงสุดในวิศวกรรมซอฟต์แวร์ดูรายการที่ 11): วัตถุที่ซ่อนข้อมูล (ดูรายการที่ 41) และประดิษฐ์ abstractions ที่แม่นยำสำหรับการคัดลอกข้อมูลผ่านผู้สร้างและผู้ดำเนินการกำหนด (ดูรายการ 52 ถึง 55) . การลิดรอนสิ่งที่มีmemcpy
การละเมิดข้อมูลอย่างจริงจังและมักจะนำไปสู่การรั่วไหลของหน่วยความจำและทรัพยากร (ที่ดีที่สุด), ล่ม (แย่กว่า) หรือพฤติกรรมที่ไม่ได้กำหนด (เลวร้ายที่สุด) - มาตรฐานการเข้ารหัส C ++
นักพัฒนา C หลายคนจะไม่เห็นด้วยกับสิ่งนี้และถูกต้องเนื่องจากปรัชญานี้ใช้เฉพาะเมื่อคุณเขียนโค้ดใน C ++ คุณมักจะเขียนโค้ดมีปัญหามากถ้าคุณใช้ฟังก์ชั่นเช่นmemcpy
เวลาทั้งหมดในรหัสที่สร้างเป็น C ++แต่ก็สมบูรณ์ดีถ้าคุณทำมันใน C ทั้งสองภาษามีความแตกต่างกันมากในเรื่องนี้เนื่องจากความแตกต่างในระบบประเภท มันดึงดูดมากที่จะดูที่คุณสมบัติย่อยทั้งสองนี้มีเหมือนกันและเชื่อว่าสามารถใช้งานได้เหมือนกันโดยเฉพาะอย่างยิ่งในด้าน C ++ แต่ C + รหัส (หรือรหัส C -) มักเป็นปัญหามากกว่าทั้ง C และ รหัส C ++
เช่นเดียวกันกับที่คุณไม่ควรใช้พูดmalloc
ในบริบทของสไตล์ C (ซึ่งไม่เกี่ยวข้องกับ EH) หากสามารถเรียกใช้ฟังก์ชัน C ++ ใด ๆ โดยตรงซึ่งสามารถโยนได้ตั้งแต่นั้นมาคุณมีจุดออกโดยปริยายในฟังก์ชันของคุณซึ่งเป็นผลมาจาก ข้อยกเว้นที่คุณไม่สามารถตรวจจับการเขียนโค้ด C ได้อย่างมีประสิทธิภาพก่อนที่จะสามารถใช้free
หน่วยความจำนั้นได้ ดังนั้นเมื่อใดก็ตามที่คุณมีแฟ้มที่สร้างเป็น C ++ กับที่.cpp
ขยายหรืออะไรก็ตามและมันไม่ประเภทเหล่านี้ทั้งหมดของสิ่งที่ชอบmalloc
, memcpy
, memset
,qsort
ฯลฯ มันจะถามปัญหาเพิ่มเติมในบรรทัดถ้าไม่ได้อยู่แล้วยกเว้นว่าจะเป็นรายละเอียดการใช้งานของคลาสที่ทำงานกับชนิดดั้งเดิมเท่านั้นซึ่ง ณ จุดนั้นยังคงต้องดำเนินการยกเว้นเพื่อความปลอดภัย หากคุณเขียนรหัส c ++ คุณแทนต้องการโดยทั่วไปพึ่งพา RAII และใช้สิ่งที่ชอบvector
, unique_ptr
, shared_ptr
ฯลฯ และหลีกเลี่ยงปกติการเข้ารหัสแบบ C เมื่อเป็นไปได้
เหตุผลที่คุณสามารถเล่นกับใบมีดโกนในประเภทข้อมูล C และ X-ray และเล่นกับบิตและไบต์ของพวกเขาโดยไม่เกิดความเสียหายต่อหลักประกันในทีม (แม้ว่าคุณยังสามารถทำร้ายตัวเองด้วยวิธีใดก็ตาม) ไม่ใช่เพราะสิ่ง C ประเภทสามารถทำได้ แต่เนื่องจากสิ่งที่พวกเขาจะไม่สามารถทำได้. ทันทีที่คุณขยายระบบประเภท C เพื่อรวมคุณสมบัติ C ++ เช่น ctors, dtors และ vtables พร้อมกับการจัดการข้อยกเว้นรหัส C สำนวนทั้งหมดจะแสดงผลไกลอันตรายมากกว่าที่เป็นอยู่ในปัจจุบันและคุณจะเห็นรูปแบบใหม่ของ ปรัชญาและความคิดการพัฒนาซึ่งจะส่งเสริมให้รูปแบบที่แตกต่างกันอย่างสมบูรณ์ของการเขียนโปรแกรมตามที่คุณเห็นใน C ++ ซึ่งขณะนี้ถือว่าแม้จะใช้การทุจริตต่อหน้าที่ชี้ดิบสำหรับการเรียนที่จัดการหน่วยความจำตรงข้ามที่จะพูด, RAII unique_ptr
สอดคล้องทรัพยากรเช่น ความคิดนั้นไม่ได้พัฒนาไปจากความปลอดภัยอย่างแท้จริง มันพัฒนามาจากสิ่งที่ C ++ ต้องการโดยเฉพาะอย่างยิ่งที่จะปลอดภัยต่อคุณสมบัติเช่นการจัดการข้อยกเว้นเนื่องจากสิ่งที่มันอนุญาตให้ผ่านระบบประเภทของมัน
ข้อยกเว้นความปลอดภัย
อีกครั้งที่คุณอยู่ในดินแดน C ++ ผู้คนจะคาดหวังว่ารหัสของคุณจะปลอดภัยยกเว้น ผู้คนอาจรักษารหัสของคุณในอนาคตเนื่องจากมันเขียนแล้วและคอมไพล์ใน C ++ และใช้std::vector, dynamic_cast, unique_ptr, shared_ptr
ฯลฯ ในรหัสที่เรียกว่าไม่ว่าโดยตรงหรือโดยอ้อมโดยรหัสของคุณโดยเชื่อว่ามันไม่น่ากลัว รหัส. ณ จุดนั้นเราต้องเผชิญหน้ากับโอกาสที่สิ่งต่าง ๆ จะโยนออกไปและเมื่อคุณใช้รหัส C ที่สวยงามและน่ารักอย่างสมบูรณ์แบบ:
int some_func(int n, ...)
{
int* x = calloc(n, sizeof(int));
if (x)
{
f(n, x); // some function which, now being a C++ function, may
// throw today or in the future.
...
free(x);
return success;
}
return fail;
}
... ตอนนี้มันพัง จะต้องมีการเขียนใหม่เพื่อให้มีข้อยกเว้น:
int some_func(int n, ...)
{
int* x = calloc(n, sizeof(int));
if (x)
{
try
{
f(n, x); // some function which, now being a C++ function, may
// throw today or in the future (maybe someone used
// std::vector inside of it).
}
catch (...)
{
free(x);
throw;
}
...
free(x);
return success;
}
return fail;
}
Gross! นี่คือเหตุผลที่นักพัฒนา C ++ ส่วนใหญ่ต้องการสิ่งนี้แทน:
void some_func(int n, ...)
{
vector<int> x(n);
f(x); // some function which, now being a C++ function, may throw today
// or in the future.
}
ข้างต้นเป็น RAII สอดคล้องรหัสยกเว้นปลอดภัยของชนิดที่ c ++ throw
นักพัฒนาโดยทั่วไปจะอนุมัติตั้งแต่ฟังก์ชั่นจะไม่รั่วไหลไม่มีที่บรรทัดของรหัสเรียกทางออกนัยเป็นผลมาจากการ
เลือกภาษา
คุณควรยอมรับระบบและปรัชญาของ C ++ กับ RAII, ข้อยกเว้นด้านความปลอดภัย, แม่แบบ, OOP, ฯลฯ หรือโอบกอด C ซึ่งส่วนใหญ่หมุนรอบบิตดิบและไบต์ คุณไม่ควรสร้างการแต่งงานที่ไม่บริสุทธิ์ระหว่างสองภาษานี้และแยกพวกเขาออกเป็นภาษาต่าง ๆ เพื่อให้ได้รับการปฏิบัติที่แตกต่างกันมากแทนที่จะเบลอพวกเขาด้วยกัน
ภาษาเหล่านี้ต้องการแต่งงานกับคุณ โดยทั่วไปคุณต้องเลือกอย่างใดอย่างหนึ่งแทนการออกเดทและเล่นกับทั้งคู่ หรือคุณอาจเป็น polygamist อย่างฉันและแต่งงานทั้งคู่ แต่คุณต้องเปลี่ยนความคิดของคุณอย่างสมบูรณ์เมื่อใช้เวลากับอีกคนหนึ่งและแยกพวกเขาออกจากกันเพื่อให้พวกเขาไม่ได้ต่อสู้กัน
ขนาดไบนารี
เพิ่งอยากรู้อยากเห็นฉันพยายามใช้รายการฟรีของฉันและมาตรฐานในขณะนี้และย้ายไปยัง C ++ เนื่องจากฉันอยากรู้เกี่ยวกับเรื่องนี้:
[... ] ไม่รู้ว่ามันจะเป็นอย่างไรเพราะฉันไม่ได้ใช้คอมไพเลอร์ C
... และต้องการทราบว่าขนาดไบนารีจะพองได้เพียงแค่สร้างเป็น C ++ หรือไม่ มันทำให้ฉันต้องพรมออกไปอย่างชัดเจนทั่วสถานที่ซึ่งน่าเกลียด (เหตุผลหนึ่งที่ฉันชอบเขียนสิ่งที่ต่ำเช่นตัวจัดสรรและโครงสร้างข้อมูลใน C ดีกว่า) แต่ใช้เวลาเพียงไม่กี่นาที
นี้เป็นเพียงการเปรียบเทียบ MSVC 64 บิตปล่อยสร้างสำหรับแอปคอนโซลที่เรียบง่ายและมีรหัสที่ไม่ได้ใช้ C ++ ใด ๆ คุณสมบัติไม่ได้ดำเนินงานมาก - เพียงแค่ความแตกต่างระหว่างการสร้างมันด้วย C และการใช้การพูด, <cstdlib>
แทน<stdlib.h>
และ สิ่งต่าง ๆ เช่นนั้น แต่ฉันประหลาดใจที่พบว่ามันสร้างความแตกต่างให้กับขนาดไบนารี่!
ไบนารีคือ9,728
ไบต์เมื่อมันถูกสร้างขึ้นใน C และในทำนองเดียวกัน9,278
ไบต์เมื่อรวบรวมเป็นรหัส C ++ ฉันไม่ได้คาดหวังสิ่งนั้นจริงๆ ฉันคิดว่าสิ่งต่าง ๆ เช่น EH อย่างน้อยก็จะเพิ่มนิดหน่อยที่นั่น (คิดว่าอย่างน้อยก็จะเหมือนร้อยไบต์ที่แตกต่างกัน) แม้ว่าอาจจะสามารถที่จะคิดว่าไม่จำเป็นต้องเพิ่มคำแนะนำที่เกี่ยวข้องกับ EH เพราะฉันเพิ่ง ใช้ไลบรารี่มาตรฐาน C และไม่มีอะไรผิดพลาด ฉันคิดอะไรบางอย่างจะเพิ่มขนาดไบนารีลงไปเล็กน้อยเช่น RTTI อย่างไรก็ตามมันก็เจ๋งดีที่เห็นว่า แน่นอนฉันไม่คิดว่าคุณควรพูดคุยจากผลลัพธ์นี้ แต่อย่างน้อยก็ทำให้ฉันประทับใจเล็กน้อย มันไม่ได้ส่งผลกระทบต่อมาตรฐานและเป็นธรรมชาติดังนั้นเนื่องจากฉันคิดว่าขนาดไบนารีที่เหมือนกันที่เกิดขึ้นนั้นก็หมายถึงคำแนะนำของเครื่องที่เกิดขึ้นเหมือนกัน
ที่กล่าวว่าใครสนใจขนาดไบนารีด้วยประเด็นความปลอดภัยและวิศวกรรมที่กล่าวถึงข้างต้น ดังนั้นอีกครั้งเลือกภาษาและยอมรับปรัชญาของมันแทนที่จะพยายามลบล้างมัน นั่นคือสิ่งที่ฉันแนะนำ
//
แสดงความคิดเห็นได้ ถ้ามันใช้งานได้ทำไมล่ะ?