มีเหตุผลใดที่จะใช้ C ++ แทน C, Perl, Python และอื่น ๆ ? [ปิด]


164

ในฐานะนักพัฒนา Linux (ฝั่งเซิร์ฟเวอร์) ฉันไม่รู้ว่าที่ไหนและเพราะเหตุใดฉันจึงควรใช้ C ++

เมื่อฉันจะไปแสดงตัวเลือกแรกและสุดท้ายคือ C

เมื่อ "ประสิทธิภาพ" ไม่ใช่ปัญหาหลักภาษาการเขียนโปรแกรมเช่น Perl และ Python จะเป็นตัวเลือกที่ดี

เกือบทุกแอพพลิเคชั่นโอเพนซอร์ซที่ฉันรู้จักในพื้นที่นี้เขียนด้วยภาษา C, Perl, Python, Bash script, AWKหรือแม้แต่ PHP แต่ไม่มีใครใช้ C ++

ฉันไม่ได้พูดถึงเรื่องอื่น ๆ เช่น GUI หรือเว็บแอปพลิเคชันฉันแค่พูดถึง Linux, CLI และ daemons

มีเหตุผลที่น่าพอใจในการใช้ C ++ หรือไม่?


5
ฉันพิจารณา C ++ เพียงเพราะ STL
dan_waterworth

46
ดังนั้นสิ่งที่สามารถทำได้โดยใช้ C, Perl และงูใหญ่ร่วมกันสามารถทำได้โดยใช้ C ++ เท่านั้น และคุณถามว่าทำไมต้องใช้ C ++
Manoj R

36
«เมื่อฉันจะไปแสดงตัวเลือกแรกและตัวสุดท้ายคือ C. »ใช่แน่นอน: D นี่เป็นการยืนยันที่ไม่ได้พิสูจน์และผิดเล็กน้อย
deadalnix

16
@deadalnix: ฉันจะไม่พูดอย่างนั้น C ++ มีกฎที่ซับซ้อนซึ่งอาจย้อนกลับมาที่เครื่องมือเพิ่มประสิทธิภาพเนื่องจากไม่อนุญาตให้ทำบางสิ่ง และมันง่ายมากที่จะก้าวเข้าสู่นักฆ่าประสิทธิภาพที่มองไม่เห็น มันเป็นจริงมากและเป็นจริงดังนั้น: D ในความเป็นจริงรหัส C ++ บางครั้งจะเร็วขึ้นเพราะคุณจะใช้อัลกอริทึมและโครงสร้างข้อมูลที่มีประสิทธิภาพมากขึ้นและไม่มีใครเพิ่มประสิทธิภาพรหัส C จริง ๆ ดังนั้นเมื่อทำอย่างถูกต้อง C ++ จะปลอดภัยกว่าและมีประสิทธิภาพมากกว่าและคุณควรเลือก C ++ เหนือ C เมื่อไม่มีปัญหาความเข้ากันได้หรือข้อกำหนดสำหรับซอฟต์แวร์ความพร้อมใช้งาน 100%
Coder

4
เหตุผลที่ดีที่สุดไม่เกี่ยวข้องกับคำตอบที่โพสต์เกี่ยวข้องกับคำถามของ OP โดยตรง DEPENDANCIES !!!!, ไม่ใช่ว่าระบบโดยเฉลี่ยของคุณไม่มี c ++ libs แต่ระบบฝังตัวอาจไม่มีให้ใช้ วิธีเดียวที่จะทำให้โปรแกรมของคุณในทุก ๆ ระบบคือการเขียนโปรแกรมของคุณในแบบปกติ C ทุกอย่างอื่นเป็นเพียงการถกเถียงว่าทำไมคุณควรแสดงน้อยกว่าไม่ควรใช้ C ++ ไม่มีเหตุผลใดที่ระบุว่าทำไม C ++ ไม่ได้ถูกใช้บ่อยกว่าและไม่คำนึงถึงข้อดีเหตุผลคือการพึ่งพา .... O และ cus rant ที่โด่งดังของ Linus
JM Becker

คำตอบ:


308

เมื่อฉันจะไปแสดงตัวเลือกแรกและสุดท้ายคือ C

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

แต่โดยทั่วไปแล้วเหตุผลในการใช้ภาษา C ++ มากกว่าภาษาอื่น ๆ นั้นก็คือประสิทธิภาพ เหตุผลก็คือ C ++ เสนอวิธีการที่เป็นนามธรรมซึ่งแตกต่างจากภาษาอื่น ๆทั้งหมดที่ฉันรู้ไม่มีค่าใช้จ่ายประสิทธิภาพที่รันไทม์

วิธีนี้ช่วยให้การเขียนโค้ดมีประสิทธิภาพมากซึ่งยังคงมีระดับนามธรรมสูงมาก

พิจารณา abstractions ปกติ: ฟังก์ชั่นเสมือนพอยน์เตอร์ของฟังก์ชั่นและสำนวน PIMPL สิ่งเหล่านี้ทั้งหมดขึ้นอยู่กับทิศทางที่แก้ไขโดยใช้ตัวชี้ทางคณิตศาสตร์ กล่าวอีกนัยหนึ่งมันเกิดค่าใช้จ่ายด้านประสิทธิภาพ (อย่างไรก็ตามอาจมีขนาดเล็ก)

ในขณะที่ C ++ นั้นมีกลไกทางอ้อมที่ไม่มีต้นทุน(ประสิทธิภาพ): เทมเพลต (ความได้เปรียบนี้จ่ายให้โดยมีเวลารวบรวมเพิ่มขึ้น (บางครั้งอย่างมหาศาล))

ลองพิจารณาตัวอย่างของฟังก์ชั่นการจัดเรียงทั่วไป

ใน C ฟังก์ชั่นqsortรับฟังก์ชั่นตัวชี้ฟังก์ชั่นที่ใช้ตรรกะโดยองค์ประกอบที่จะถูกจัดเรียงสัมพันธ์กับอีกคนหนึ่ง Arrays.sortฟังก์ชันของ Java มีหลากหลายรูปแบบ หนึ่งของพวกเขาเรียงลำดับวัตถุโดยพลการและต้องใช้วัตถุที่ถูกส่งผ่านไปที่ทำงานเหมือนตัวชี้ฟังก์ชั่นในซีComparator qsortแต่มีโอเวอร์โหลดจำนวนมากสำหรับประเภท "ดั้งเดิม" ของ Java และแต่ละคนก็มีวิธีการของตัวเองsort- การทำซ้ำรหัสที่น่ากลัว

Java แสดงให้เห็นถึงการแบ่งขั้วทั่วไปที่นี่: คุณมีการทำซ้ำรหัสหรือคุณมีค่าใช้จ่ายรันไทม์

ใน C ++ sortฟังก์ชั่นทำงานคล้ายกับqsortใน C มีความแตกต่างเพียงเล็กน้อย แต่พื้นฐาน: ตัวเปรียบเทียบที่ส่งผ่านเข้าไปในฟังก์ชันนั้นเป็นพารามิเตอร์เทมเพลต นั่นหมายความว่าการเรียกร้องของมันสามารถinlined ไม่จำเป็นต้องมีการเปรียบเทียบทางอ้อมเพื่อเปรียบเทียบสองวัตถุ ในวงแคบ (เช่นกรณีที่นี่) จริง ๆ แล้วสามารถสร้างความแตกต่างมากมาย

ไม่น่าแปลกใจที่sortฟังก์ชันC ++ มีประสิทธิภาพสูงกว่า C sortถึงแม้ว่าอัลกอริทึมพื้นฐานจะเหมือนกัน นี่เป็นสิ่งที่สังเกตเห็นได้ชัดเจนเมื่อตรรกะการเปรียบเทียบจริงราคาถูก

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


16
ตอนนี้ฉันรู้เพียงพอเกี่ยวกับ C ++ เพื่อทราบว่าคุณอยู่ในจุดที่ผิดหรือผิด แต่ยังต้องการที่จะเพิ่มคุณได้รับเพียง 1 downvote ดังนั้นผ่อนคลาย นี่คืออินเทอร์เน็ตและ downvotes เกิดขึ้น คำตอบที่ดีแม้ว่าถ้ามันฟังดูทางเทคนิค!
Chris

46
ไม่มีค่าใช้จ่ายด้านประสิทธิภาพในการทำงาน - นั่นไม่จริงเสมอไป หากคุณดูการใช้งานเวกเตอร์ STL คุณจะเห็นว่าพวกเขาไม่ได้ใช้ประโยชน์จากการใช้ realloc () (ไม่สามารถทำได้เพราะตัวชี้เรื่องยาว) ในขณะที่ภาษาระดับสูงทั้งหมดที่ฉันรู้สามารถใช้ realloc ( ) ในเวกเตอร์ของ impl นี่เป็นเพียงตัวอย่างหนึ่งที่ไม่ชัดเจนและขาวดำทั้งหมด
mojuba

19
@Jaroslaw, @Steve: แต่เหมือนเดิม (= การขยายตัวของรหัสแคชการเรียนการสอนที่ขาดหายไป) เป็นจริงสำหรับโค้ดที่ปรับปรุงด้วยมือซึ่งปรับให้เหมาะกับข้อมูลแต่ละประเภท (ดูArrays.sortการใช้งานที่หลากหลายของ Java ) มีเพียงคุณเท่านั้นที่สูญเสียความได้เปรียบจากสิ่งที่เป็นนามธรรมสูง นี่ไม่ใช่ข้อเสียของเทมเพลตโดยเฉพาะมันเป็นข้อเสียของการทำสำเนาโค้ดโดยทั่วไป นอกจากนี้สิ่งนี้มีแนวโน้มที่จะไม่สำคัญเนื่องจากในลูปแน่นมักจะเป็นรหัสเดียวกันกับที่โหลด
Konrad Rudolph

18
@Jaroslaw: สิ่งที่ตลกเกี่ยวกับแคชการเรียนการสอนก็คือว่ามันเป็นแคช นั่นคือมันไม่พยายามที่จะเก็บทุกอย่างเพียงเมื่อเร็ว ๆ นี้ใช้รหัส เทมเพลตอาจสร้างโค้ดที่คล้ายกันจำนวนมากสำหรับประเภทที่แตกต่างกัน ( vector.push_backสำหรับvector<int>และอีกอันสำหรับvector<float>แต่ในขณะที่ทำงานกับ a vector<int>มีเหตุผลเล็กน้อยว่าทำไมvector<float>รหัสจะอยู่ในแคชคำสั่งดังนั้นฉันไม่เห็นว่ามันมีความสำคัญอย่างไรแต่ละเทมเพลต instantiation คือการเพิ่มประสิทธิภาพสูงและมักจะมากขึ้นขนาดกะทัดรัดกว่าทั่วไปจับทุกการใช้งาน
jalf

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

166

ฉันเห็นโปรแกรมเมอร์ C มากเกินไปที่เกลียด C ++ ฉันใช้เวลาค่อนข้างนานหลายปีในการเข้าใจสิ่งที่ดีและสิ่งที่ไม่ดีเกี่ยวกับเรื่องนี้อย่างช้าๆ ฉันคิดว่าวิธีที่ดีที่สุดในการใช้วลีนี้คือ:

รหัสน้อยไม่มีค่าใช้จ่ายในการดำเนินการความปลอดภัยมากขึ้น

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

ต่อไปนี้เป็นตัวอย่างที่เรียบง่ายจากตัวแสดงผลของฉัน: เมื่อทำการแก้ไขค่าพิกเซลข้าม scanline ของรูปสามเหลี่ยม ฉันต้องเริ่มต้นจากพิกัด X X และถึงพิกัด X x2 (จากซ้ายไปทางด้านขวาของรูปสามเหลี่ยม) และในแต่ละขั้นตอนในแต่ละพิกเซลที่ฉันผ่านไปฉันต้องแก้ไขค่า

เมื่อฉันแก้ไขแสงโดยรอบที่มาถึงพิกเซล:

  typedef struct tagPixelDataAmbient {
      int x;
      float ambientLight;
  } PixelDataAmbient;

  ...
  // inner loop
  currentPixel.ambientLight += dv;

เมื่อฉันสอดแทรกสี (เรียกว่า "การแรเงา" Gouraud "โดยที่ฟิลด์" สีแดง "," สีเขียว "และ" สีฟ้า "ถูกแก้ไขโดยค่าขั้นตอนในแต่ละพิกเซล):

  typedef struct tagPixelDataGouraud {
      int x;
      float red;
      float green;
      float blue;  // The RGB color interpolated per pixel
  } PixelDataGouraud;

  ...
  // inner loop
  currentPixel.red += dred;
  currentPixel.green += dgreen;
  currentPixel.blue += dblue;

เมื่อฉันแสดงเป็นเงาพงษ์ฉันจะไม่สอดแทรกความเข้ม (ambientLight) หรือสี (แดง / เขียว / น้ำเงิน) อีกต่อไป - ฉันสอดแทรกเวกเตอร์ปกติ (nx, ny, nz) และในแต่ละขั้นตอนฉันต้อง - คำนวณสมการของแสงโดยใช้เวกเตอร์ตั้งฉากแบบปกติ:

  typedef struct tagPixelDataPhong {
      int x;
      float nX;
      float nY;
      float nZ; // The normal vector interpolated per pixel
  } PixelDataPhong;

  ...
  // inner loop
  currentPixel.nX += dx;
  currentPixel.nY += dy;
  currentPixel.nZ += dz;

ตอนนี้สัญชาตญาณแรกของโปรแกรมเมอร์ C คือ "heck เขียนสามฟังก์ชั่นที่สอดแทรกค่าและเรียกมันขึ้นอยู่กับโหมด set" ก่อนอื่นนี่หมายความว่าฉันมีปัญหาประเภท - ฉันจะทำงานกับอะไร PixelDataAmbient ของฉันเป็นพิกเซลหรือไม่ PixelDataGouraud? PixelDataPhong? อ๋อเดี๋ยวก่อนโปรแกรมเมอร์ C ที่มีประสิทธิภาพพูดว่าใช้งานยูเนี่ยน!

  typedef union tagSuperPixel {
      PixelDataAmbient a;
      PixelDataGouraud g;
      PixelDataPhong   p;
  } SuperPixel;

.. แล้วคุณมีฟังก์ชั่น ...

  RasterizeTriangleScanline(
      enum mode, // { ambient, gouraud, phong }
      SuperPixel left,
      SuperPixel right)
  {
      int i,j;
      if (mode == ambient) {
          // handle pixels as ambient...
          int steps = right.a.x - left.a.x;
          float dv = (right.a.ambientLight - left.a.ambientLight)/steps;
          float currentIntensity = left.a.ambientLight;
          for (i=left.a.x; i<right.a.x; i++) {
              WorkOnPixelAmbient(i, dv);
              currentIntensity+=dv;
          }
      } else if (mode == gouraud) {
          // handle pixels as gouraud...
          int steps = right.g.x - left.g.x;
          float dred = (right.g.red - left.g.red)/steps;
          float dgreen = (right.g.green - left.a.green)/steps;
          float dblue = (right.g.blue - left.g.blue)/steps;
          float currentRed = left.g.red;
          float currentGreen = left.g.green;
          float currentBlue = left.g.blue;
          for (j=left.g.x; i<right.g.x; j++) {
              WorkOnPixelGouraud(j, currentRed, currentBlue, currentGreen);
              currentRed+=dred;
              currentGreen+=dgreen;
              currentBlue+=dblue;
          }
...

คุณรู้สึกถึงความโกลาหลที่เข้ามาหรือไม่?

ก่อนอื่นหนึ่งการพิมพ์ผิดคือสิ่งที่จำเป็นในการทำให้รหัสของฉันผิดเนื่องจากคอมไพเลอร์จะไม่หยุดฉันในส่วน "Gouraud" ของฟังก์ชันเพื่อเข้าถึง ".a" อย่างแท้จริง ค่า (แวดล้อม) ข้อผิดพลาดที่ไม่ถูกจับโดยระบบชนิด C (นั่นคือระหว่างการรวบรวม) หมายถึงข้อผิดพลาดที่ปรากฏในเวลาทำงานและจะต้องมีการดีบัก คุณสังเกตเห็นว่าฉันกำลังเข้าสู่left.a.greenการคำนวณ "dgreen" หรือไม่? ผู้แปลไม่ได้บอกคุณอย่างแน่นอน

จากนั้นมีการทำซ้ำทุกที่ - forลูปมีหลายครั้งที่มีโหมดการเรนเดอร์เราทำต่อไป "ลบด้วยการหารซ้ายขวาด้วยขั้นตอน" น่าเกลียดและผิดพลาดได้ง่าย คุณสังเกตเห็นฉันเปรียบเทียบโดยใช้ "i" ใน Gouraud loop เมื่อใดที่ฉันควรใช้ "j" คอมไพเลอร์นั้นเงียบอีกครั้ง

สิ่งที่เกี่ยวกับ if / else / ladder สำหรับโหมด? จะเกิดอะไรขึ้นถ้าฉันเพิ่มโหมดการแสดงผลใหม่ในสามสัปดาห์ ฉันจะจำได้หรือไม่ว่าจะจัดการโหมดใหม่ใน "if mode ==" ในรหัสของฉันทั้งหมดหรือไม่

ตอนนี้เปรียบเทียบความอัปลักษณ์ข้างต้นด้วยชุด C ++ structs และฟังก์ชันเทมเพลต:

  struct CommonPixelData {
      int x;
  };
  struct AmbientPixelData : CommonPixelData {
      float ambientLight;
  };
  struct GouraudPixelData : CommonPixelData {
      float red;
      float green;
      float blue;  // The RGB color interpolated per pixel
  };
  struct PhongPixelData : CommonPixelData {
      float nX;
      float nY;
      float nZ; // The normal vector interpolated per pixel
  };

  template <class PixelData>
  RasterizeTriangleScanline(
      PixelData left,
      PixelData right)
  {
      PixelData interpolated = left;
      PixelData step = right;
      step -= left;
      step /= int(right.x - left.x); // divide by pixel span
      for(int i=left.x; i<right.x; i++) {
          WorkOnPixel<PixelData>(interpolated);
          interpolated += step;
      }
  }

ตอนนี้ดูที่นี้ เราไม่ได้ทำซุปรวมยูเนี่ยนอีกต่อไป: เรามีประเภทเฉพาะต่อแต่ละโหมด พวกเขาใช้สิ่งทั่วไป (ฟิลด์ "x") อีกครั้งโดยสืบทอดจากคลาสพื้นฐาน ( CommonPixelData) และเทมเพลตทำให้คอมไพเลอร์สร้าง (นั่นคือรหัสสร้าง) สามฟังก์ชั่นที่แตกต่างกันเราจะได้เขียนตัวเองใน C แต่ในเวลาเดียวกันการเข้มงวดมากเกี่ยวกับประเภท!

การวนซ้ำของเราในเทมเพลตไม่สามารถทำให้ผิดและเข้าถึงฟิลด์ที่ไม่ถูกต้อง - คอมไพเลอร์จะเห่าถ้าเราทำ

เทมเพลตดำเนินงานทั่วไป (ลูปเพิ่มขึ้นโดย "ขั้นตอน" ในแต่ละครั้ง) และสามารถทำได้ในลักษณะที่ไม่สามารถทำให้เกิดข้อผิดพลาดรันไทม์ แก้ไขต่อประเภท ( AmbientPixelData, GouraudPixelData, PhongPixelData) จะทำกับoperator+=()ว่าเราจะเพิ่มใน structs - ซึ่งโดยทั่วไปกำหนดวิธีการแต่ละประเภทจะถูกหยัน

และคุณเห็นสิ่งที่เราทำกับ WorkOnPixel <T> หรือไม่ เราต้องการทำงานที่แตกต่างกันตามประเภทหรือไม่ เราเรียกความเชี่ยวชาญเฉพาะด้านเทมเพลต:

void WorkOnPixel<AmbientPixelData>(AmbientPixelData& p)
{
    // use the p.ambientLight field
}


void WorkOnPixel<GouraudPixelData>(GouraudPixelData& p)
{
    // use the p.red/green/blue fields
}

นั่นคือ - ฟังก์ชั่นการโทรจะตัดสินใจตามประเภท ที่รวบรวมเวลา!

ในการใช้ถ้อยคำใหม่อีกครั้ง:

  1. เราย่อโค๊ด (ผ่านเทมเพลต) นำชิ้นส่วนทั่วไปกลับมาใช้ใหม่
  2. เราไม่ใช้แฮ็กที่น่าเกลียดเราใช้ระบบแบบเข้มงวดเพื่อให้คอมไพเลอร์สามารถตรวจสอบเราได้ตลอดเวลา
  3. และดีที่สุด: ไม่มีสิ่งที่เราทำมีผลกระทบต่อรันไทม์ใด ๆ รหัสนี้จะเรียกใช้เพียงเร็วเท่ารหัส C เทียบเท่า - ในความเป็นจริงถ้ารหัส C ใช้ฟังก์ชันพอยน์เตอร์เพื่อเรียกใช้WorkOnPixelรุ่นต่าง ๆรหัส C ++ จะเร็วกว่า C เนื่องจากคอมไพเลอร์จะอินไลน์WorkOnPixelแม่แบบเฉพาะประเภท โทร!

รหัสน้อยไม่มีค่าใช้จ่ายในการดำเนินการความปลอดภัยมากขึ้น

สิ่งนี้หมายความว่า C ++ เป็นภาษาที่เป็นทั้งหมดและสิ้นสุดหรือไม่ ไม่แน่นอน คุณยังต้องวัดการแลกเปลี่ยน คนที่โง่เขลาจะใช้ C ++ เมื่อพวกเขาควรเขียนสคริปต์ Bash / Perl / Python มือใหม่ C ++ ที่มีความสุขในการเรียกใช้จะสร้างคลาสที่ซ้อนกันอย่างลึกล้ำด้วยการสืบทอดหลาย ๆ แบบเสมือนจริงก่อนที่คุณจะหยุดและส่งพวกมันออก พวกเขาจะใช้การเขียนโปรแกรมBoost meta ที่ซับซ้อนก่อนที่จะรู้ว่าสิ่งนี้ไม่จำเป็น พวกเขาจะยังคงใช้char*, strcmpและแมโครแทนstd::stringและแม่แบบ

แต่นี่ไม่ได้พูดอะไรมากไปกว่า ... ดูว่าคุณทำงานกับใคร ไม่มีภาษาใดที่จะป้องกันคุณจากผู้ใช้ที่ไร้ความสามารถ (ไม่แม้แต่ Java)

ศึกษาและใช้ C ++ ต่อไป - อย่าเพิ่งออกแบบมากเกินไป


18
+1 สำหรับ "ไม่ไม่ใช่แม้แต่ Java" :)
นาธานออสมัน

53
+1 สำหรับตัวอย่าง มันเป็นการโพสต์ที่ยาวนาน แต่การเปรียบเทียบระหว่างรหัส C และ C ++ นั้นน่าประทับใจ
paercebal

และนี่คือท่านสุภาพบุรุษและสุภาพสตรีนี่คือเหตุผลที่ lex / yacc มีอยู่จริง ด้วยเหตุผลเดียวกันฉันไม่เคยรู้เลยว่าบางส่วนของ c ++ ตกอยู่ในปรัชญาการสร้างรหัสเดียวกัน ฉันจะต้องดูอีกครั้ง
Spencer Rathbun

2
ฉันได้เขียนโค้ดการเรนเดอร์ 2D จำนวนมาก (มากกว่าทศวรรษที่แล้ว) และพบปัญหานี้ในขณะที่ย้ายจาก C ถึง C ++: คุณจะกำหนดโครงสร้างของพิกเซลได้อย่างไรหาก scanline ของคุณทำจากพิกเซล 1 บิต (8 พิกเซลใน ไบต์) และเมื่อ scanline ของคุณทำจาก R, G และ B (3 ไบต์ต่อพิกเซล)? และเมื่อคุณมีบัฟเฟอร์สามชุดสำหรับ R, G และ B คุณรู้คำตอบ: C ++ ไม่มีความช่วยเหลือที่นั่นและการยืนยันการใช้แม่แบบจะทำให้คุณเสียพื้นที่และเวลาในการปรับให้เหมาะสมที่สุด
Walter Tross

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

79

RAIIสำหรับผู้ชนะ

การทำลายล้างที่กำหนดขึ้นอย่างจริงจังใน C ++ ทำให้โค้ดมีความชัดเจนและปลอดภัยยิ่งขึ้นโดยไม่มีค่าใช้จ่ายใด ๆ ทั้งสิ้น


20
"C ++: ทางเลือกเดียวที่กำหนดอย่างจริงจังถามแพทย์ของคุณเกี่ยวกับเรื่องนี้ในวันนี้"
Kyle Strand

2
การติดตาม: สนิมเป็นคู่แข่งในสาขานี้ ดูตัวอย่าง RAII พื้นฐานและเอกสารเกี่ยวกับวิธีการ destructor สนิมของ
Kyle Strand

1
C จะถูกกำหนดไว้ แต่ต้องใช้งานมากขึ้นเพื่อให้แน่ใจว่ามันจะเกิดขึ้นจริงเมื่อใช้หน่วยความจำ malloc-ed
Baldrickk

1
@Baldrickk ใน C คุณต้องเขียนโค้ดการล้างข้อมูลทุกที่ที่คุณใช้ทรัพยากร ใน C ++ คุณเขียนหนึ่งครั้งในนิยามของทรัพยากร ทั้ง C และ Java ทุกข์ทรมานจาก "ทรัพยากรที่ใช้หลังจากที่จำหน่าย" และ "การรั่วไหลของทรัพยากร" ข้อบกพร่องเพราะการทำความสะอาดไม่ได้เป็นไปโดยอัตโนมัติ หน่วยความจำไม่ได้เป็นเพียงทรัพยากร
Caleth

70

มีเหตุผลที่น่าพอใจในการใช้ C ++ หรือไม่?

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

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

  2. การประมวลผลข้อความใน C ++ เป็นคำสั่งที่มีขนาดความเจ็บปวดน้อยกว่าใน C


35
+1 สำหรับการประมวลผลข้อความซึ่งฉันลืมไปโดยสิ้นเชิงในคำตอบของฉัน
Konrad Rudolph

8
ฉันพบว่าการประมวลผลข้อความเจ็บปวดโดยเฉพาะอย่างยิ่งเมื่อเทียบกับ Python ..
Nils

7
Boost เป็นเหตุผลเดียวที่ฉันยังคงใช้ C ++
Ferruccio

33
@ นิลส์: ในระดับ 1 ถึงความเจ็บปวดการประมวลผลข้อความใน C ++ นั้นแย่กว่าในภาษาสมัยใหม่เช่น Python เป็นเพียงการประมวลผลข้อความใน C กำหนดความเจ็บปวดในตูด หากตัวเลือกอยู่ระหว่าง C และ C ++ สำหรับแอปพลิเคชันนั้น ๆ C ++ จะชนะได้อย่างง่ายดาย
John Bode

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

41

ใช่.

หากคุณกำลังมองหาประสิทธิภาพในการปฏิบัติงานคุณอยู่ที่ C หรือ C ++ ดังนั้นฉันจะมุ่งเน้นที่

แม้กระทั่งก่อนที่แม่อยู่ร่วมกันฉันต้องการใช้ C ++ กว่า C เป็นชนิดของ executables ที่คุณหารือเป็นช่วงต้นกลางปี 1990 ด้วยเหตุผลสองประการง่ายมาก: polymorphism วัตถุและRAII

ฉันใช้วัตถุ C + + polymorphic สำหรับทุกสิ่งที่น่าสนใจ ตัวอย่างเช่นฉันทำงานกับระบบ Linux ที่ฝังตัวพร้อมเฟรมบัฟเฟอร์แบบซ้อนทับบนซีพียู OMAP และ XScale ARM สถาปัตยกรรมฮาร์ดแวร์ทั้งสองมีคุณสมบัติการซ้อนทับที่แตกต่างกันด้วย API ที่แตกต่างกันมาก ฉันใช้คลาสพื้นฐาน "โอเวอร์เลย์" เสมือนทั่วไปเพื่อแสดงมุมมองในอุดมคติของการวางซ้อนจากนั้นจึงเขียนคลาส "OmapOverlay" และ "XScaleOverlay" ซึ่งถูกสร้างอินสแตนซ์ที่เหมาะสมในขณะใช้งานจริงขึ้นอยู่กับสถาปัตยกรรมที่รหัสตรวจพบว่าทำงานอยู่

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

ฉันรู้อยู่เต็มอกว่าคุณสามารถทำสิ่งเหล่านี้ด้วย C - มันเป็นงานที่มากขึ้นวิธีการเขียนโค้ดที่มากขึ้นและสิ่งที่คุณจบลงด้วยการเป็นคนขี้เหร่และมักจะเข้าใจยากกว่า มีรหัสความแตกต่างกันทั่วinternals เซิร์ฟเวอร์ Xและคนมันเป็น fugly และแปลกและยากที่จะติดตามบ่อย

ฉันยังทำงานกับเทคโนโลยี GNOME จำนวนมากเช่น GTK + และ Clutter ซึ่งทั้งหมดเขียนด้วยภาษา C โดยใช้ระบบ GObject GObject เป็นเหมือนระบบวัตถุ C ++ ที่มีฝาครอบที่สวยงามถูกถอดออกและมีการเปิดใช้งานภายในที่น่าเกลียดและมักจะต้องใช้โค้ดครึ่งโหลเพื่อทำสิ่งที่การเรียกใช้เมธอด C ++ แบบบรรทัดเดียว ฉันกำลังเขียนบางอย่างClutterActorsและในขณะที่คณิตศาสตร์นั้นน่าสนใจจริง ๆ ฉันก็คิดอยู่ตลอดเวลาว่า

ฉันมักจะคิดว่า "คุณรู้ไหมถ้าฉันเขียนสิ่งนี้ใน C ++ แทนที่จะเป็น C ฉันจะออกไปอยู่ในห้องนั่งเล่นเพื่อดูMythBustersกับภรรยาของฉันแทนที่จะนั่งในออฟฟิศเวลา 21.00 น."


9
ฉันสามารถเกี่ยวข้องกับสิ่งที่คุณพูดที่นี่โดยเฉพาะอย่างยิ่ง 1) ประเด็นเกี่ยวกับ RAII และ 2) ความคิด "คุณรู้ไหมถ้าฉันเขียนสิ่งนี้ใน C ++ แทนที่จะเป็น C ... " ฉันพัฒนาระบบฝังตัวมากมาย และแม้ว่าทีมจะเป็นร้านค้าประเภท "C" หรือ "C ที่มีคลาส" ฉันพยายามสนับสนุน RAII สำหรับสิ่งต่าง ๆ เช่นการจัดการขัดจังหวะการดำเนินการ mutex และการติดตาม / การบันทึก (โดยเฉพาะสิ่งต่าง ๆ เช่นการสลับ I / O บรรทัด) และรายละเอียดของคุณเกี่ยวกับเฟรมบัฟเฟอร์โพลีมอร์ฟิคทำให้ฉันนึกถึงการใช้บัฟเฟอร์ข้อความโพลีมอร์ฟิคในระบบกระจาย
เรเดียน

29

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

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

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


13
นอกจากนี้ไม่มีกรณีที่ C ++ จะช้ากว่า C เพราะคุณสามารถใช้วิธี C ถ้ามันจะเร็ว (และคุณสนใจ)
Jack Aidley

1
@JackAidley - ยกเว้นว่า C ++ ไม่รองรับพารามิเตอร์ จำกัด และพารามิเตอร์อาร์เรย์แบบคงที่ และยกเว้นว่าใช้สไตล์ C ++ ในที่เดียวบังคับให้คุณใช้ที่อื่น
martinkunev

@martinkunev restrictใช้เพื่อแยกออกจากการเพิ่มประสิทธิภาพนามแฝงดังนั้นวิธีการที่จะช่วยทำให้สิ่งต่าง ๆเร็วขึ้น ? และ "พารามิเตอร์อาร์เรย์คงที่" คืออะไร? และ "สไตล์" มีผลต่อประสิทธิภาพอย่างไร
underscore_d

1
@underscore_d จำกัด การอนุญาตให้เพิ่มประสิทธิภาพขึ้นอยู่กับการรับประกันสำหรับการไม่ใช้นามแฝง; พารามิเตอร์อาร์เรย์แบบสแตติกให้คอมไพเลอร์สันนิษฐานว่าอาร์กิวเมนต์ตัวชี้ไม่ใช่ NULL และตัวชี้นี้ชี้ไปที่จำนวนองค์ประกอบที่กำหนดอย่างน้อย คำว่า "สไตล์" มีความหมายหลายอย่างและทำให้บริบทเปลี่ยนความหมายของมันออกไป - ฉันกำลังพูดถึงวิธีการยกตัวอย่างเช่นข้อยกเว้นบังคับให้ใช้พอยน์เตอร์อัจฉริยะ
martinkunev

1
@ smartinkunev อืมดังนั้นฉันสงสัยว่าพารามิเตอร์อาร์เรย์แบบคงที่ทำให้สิ่งที่ใช้งานได้แตกต่างจากเทมเพลต C ++ ที่ใช้ a T (&arr)[n]หรือstd::array<T, n>- จะต้องค้นคว้าข้อมูลนี้อีกเนื่องจากมีข้อมูลไม่มากนัก นั่นเป็นเหตุผลที่เป็นตัวอย่างที่ดี หากการเขียนโค้ดบนสนามเด็กเล่นเท่ากันเราจะไม่ใช้ข้อยกเว้นดังนั้นจึงไม่มีค่าใช้จ่ายที่อาจเกิดขึ้น ... แต่ฉันสงสัยว่าคุณอาจพูดพาดพิงถึงวิธีการที่เมื่อห้องสมุดของบุคคลที่สามเข้ามาในรูปภาพสมมติฐานมากมาย มีความเสี่ยง
underscore_d

27

ฉันถือว่า C ++ เป็นภาษาของปี 1990 ซึ่งเป็นภาษาของยุคอดีต

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

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

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


11
ดังนั้นอย่าเปลี่ยนการสุ่มไบต์โดยใช้พอยน์เตอร์ นั่นไม่ใช่เรื่องยากที่จะหลีกเลี่ยงใช่ไหม?
David Thornley

11
@ Blagovest: ฉันเห็นด้วยกับคุณเกี่ยวกับความซับซ้อนของ C ++ และฉันจะไม่ใช้มันเพื่อแทนที่ภาษาเชิงวัตถุ แต่ถึงแม้จะมีความซับซ้อนมันก็ยังชนะมากกว่า C สำหรับฉันเพราะมันมีข้อดีหลายอย่างที่สะกดออกมาในคำตอบที่แตกต่างกัน (นามธรรม, การส่งทรัพยากร, การจัดการสตริง ... ) ในความเป็นจริงคุณได้ตั้งชื่อพื้นที่ที่ถูกต้องไม่กี่แห่งที่ C ++ ยังคงมีความเกี่ยวข้องกันและที่ใดที่เหนือกว่า C.
Konrad Rudolph

6
@ Blagovest: นั่นเป็นเหตุผลที่ฉันอยู่ห่างจากมุมมืด มันง่ายกว่าที่จะนำไปรวมไว้ที่ C ++ มากกว่าภาษาอื่น ๆ ที่ฉันรู้จัก จากการใช้งานฉันได้รับประโยชน์จาก RAII การจัดการสตริงที่ดีกว่า C, เทมเพลตประเภท STL, คุณสมบัติ OO และข้อดีอื่น ๆ ที่มีเหนือ C.
David Thornley

24
@Blagovest: ไม่คุณไม่ต้องการ ตัวอย่างเช่นสิ่งที่คุณกล่าวถึงไม่เพียงพอที่จะบรรลุ RAII และคลาสคอนเทนเนอร์มีฟังก์ชั่นที่นอกเหนือจากโครงสร้างข้อมูลที่สร้างขึ้นด้วยมืออย่างง่าย หากคุณคิดว่าเป็นไปได้คุณจะไม่เคยเรียนรู้ C ++ อย่างดี
David Thornley

5
@Jaroslaw ฉันไม่ได้เห็นว่าทำไมเครื่องมัลติคอร์จะทำให้ OOP กลายเป็นหลุมฝังศพ ถ้าคุณหมายถึง C ++ ฉันจะเห็นว่าคุณมาจากไหน OOP เป็นแนวคิดพื้นฐานในภาษาการเขียนโปรแกรมที่ทันสมัยโดยเฉพาะอย่างยิ่งภาษาระดับสูง แม้แต่ C ก็สามารถเป็น OO ได้ถ้าคุณตั้งโปรแกรมแบบนั้น มันไม่สะดวกเท่า C ++ IMO
vedosity

21

อ้างอิงจากสไลนัสไม่มี:

เมื่อฉันดูซอร์สโค้ด Git ครั้งแรกมีสองสิ่งที่ทำให้ฉันประหลาด: 1. Pure C ตรงข้ามกับ C ++ ไม่รู้ว่าทำไม กรุณาอย่าพูดถึงการพกพามันเป็น BS

คุณเต็มไปด้วยเรื่องไร้สาระ

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

กล่าวอีกนัยหนึ่ง: การเลือก C เป็นทางเลือกที่มีเหตุผลเท่านั้น ฉันรู้ว่า Miles Bader พูดติดตลกว่า "ทำให้คุณโกรธ" แต่จริง ๆ แล้วมันเป็นเรื่องจริง ฉันได้ข้อสรุปว่าโปรแกรมเมอร์ที่ต้องการให้โครงการเป็น C ++ เหนือ C น่าจะเป็นโปรแกรมเมอร์ที่ฉัน อยากจะฉี่จริง ๆ เพื่อที่ว่าเขาจะไม่มาและทำให้โครงการที่ฉันเกี่ยวข้องเข้าด้วยกันหมด กับ

C ++ นำไปสู่ตัวเลือกการออกแบบที่ไม่ดีจริงๆ คุณเริ่มใช้คุณลักษณะไลบรารี "nice" อย่างสม่ำเสมอของภาษาเช่น STL และ Boost และอึทั้งหมดและอื่น ๆ ที่อาจ "ช่วย" โปรแกรมของคุณ แต่เป็นสาเหตุ:

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

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

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

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

หากคุณต้องการ VCS ที่เขียนด้วย C ++ ไปเล่นกับ Monotone จริงๆ. พวกเขาใช้ "ฐานข้อมูลจริง" พวกเขาใช้ "ไลบรารีเชิงวัตถุที่ดี" พวกเขาใช้ "abstractions C ++ ที่ดี" และค่อนข้างตรงไปตรงมาจากการตัดสินใจออกแบบทั้งหมดที่ฟังดูน่าดึงดูดสำหรับคน CS บางคนผลลัพธ์ที่ได้คือความยุ่งเหยิงที่น่ากลัวและไม่อาจควบคุมได้

แต่ฉันแน่ใจว่าคุณต้องการมากกว่า git

      Linus

62
ฉันไม่คิดว่าไลนัสควรเป็นคนที่จะไปโต้แย้งที่นี่ เสียงโวยวายของเขาเป็นเรื่องส่วนตัวและน่ากลัว จริง ๆ แล้วเขามีจุดดีอยู่บ้าง แต่พวกเขาถูกฝังอยู่ลึกมาก (ใต้“ พล่าม” และพล่าม) ซึ่งหายากมาก
Konrad Rudolph

19
ฮ่าฮ่านั่นเป็นเสียงหัวเราะที่ดี ฉันไม่เคยต้องการพบผู้ชายคนนี้
เฟลิกซ์ดอมเบ

30
Linus เตือนให้ฉันนึกถึงนักขับรถที่มีความสามารถผู้ซึ่งไม่เคยหยุดยั้งกับร็อคร็อค แต่เรียกคนแพนร็อคเพราะพวกเขาใช้สกรูแทนตะปู
Bob Murphy

8
ไลนัสมีประเด็น แต่แสดงให้เห็นว่ามันรุนแรงเกินไปที่จะดำเนินการอย่างจริงจัง
Blagovest Buyukliev

39
ฉันเห็นด้วยกับ @Daniel หากมีใครบางคนที่สามารถพูดคุยเกี่ยวกับการผลักดันขอบเขตของฮาร์ดแวร์คือ John Carmack ผู้สร้าง doom, quake และเกมอื่น ๆ และผู้ก่อตั้งซอฟต์แวร์ Id เขาเขียนสิ่งนี้เกี่ยวกับ c และ c ++ ใน twitt ไม่กี่เดือนที่ผ่านมา: "IMO, รหัส C ++ ที่ดีนั้นดีกว่ารหัส C ที่ดี แต่ C ++ ที่ไม่ดีสามารถมากได้ยิ่งกว่า C รหัสที่แย่มาก" twitter.com/#!/ID_AA_Carmack/status/26560399301
Onema

18

ฉันไม่คิดว่ามีเหตุผลที่น่าสนใจในการใช้ C ++ ถ้าคุณต้องการเขียนโปรแกรม OO คุณสามารถใช้ Python แทนและเขียนส่วนที่ต้องการประสิทธิภาพที่รวดเร็วใน C

แก้ไข: มีภาษาอื่น ๆ ที่เชื่อมต่อได้ดีกับ C ดังนั้นหากคุณไม่ชอบ Python ก็มีทางเลือกอื่น


3
แล้วการพัฒนาแบบฝังล่ะ Python ไม่สามารถใช้งานได้ตลอดเวลาและความแตกต่างของความเร็วระหว่าง C และ C ++ ที่เขียนได้ดีนั้นเล็กน้อยบนอุปกรณ์ที่ผ่านการประมวลผลในระดับหนึ่ง แน่นอนฉันคิดว่าคอมไพเลอร์ C ++ จะไม่สามารถใช้ได้เช่นกัน ...
James

6
@James "well
wrote

5
ฉันเห็นด้วยกับคำตอบนี้ทำระดับสูงด้วยไพ ธ อนเพราะคุณจะเขียนมันเร็วกว่าโพรไฟล์ 3 ครั้งแล้วปล่อยคอขวดโดยแทนที่ด้วย C / C ++ มันซ้ำซ้อนที่จะพูดว่า "แทนที่คอขวดด้วยรหัส C ++" เพราะคุณจะไม่ทำอะไรในระดับสูงด้วยรหัสที่คุณต้องการได้อย่างรวดเร็วเพราะมันจะเป็นรหัสระดับต่ำ มีอยู่สิ่งหนึ่ง: ฉันไม่รู้วิธีเชื่อมต่อ c ++ กับ python: / แต่ในแง่ของเวลาที่ใช้หน้าจอและประสิทธิภาพฉันคิดว่านั่นเป็นทางออกที่ดีที่สุดเนื่องจากโค้ด C ++ ส่วนใหญ่จะไม่ทำงานอย่างรวดเร็ว!
jokoon

8
ไปทำงานกับ บริษัท ทางการเงินขนาดใหญ่และสร้างระบบการเงินที่ซับซ้อนในทีมงานกระจายขนาดใหญ่ใน Python และดูว่าคุณชอบมันอย่างไร ประสบการณ์จะสอนคุณ: a) ข้อดีของความปลอดภัยประเภท b) ข้อดีของคอมไพเลอร์ที่ช่วยลดก้นของคุณ c) รหัส LUDICROUS ที่ Python อนุญาตให้ noobs เขียน มีคนบอกว่ามันง่ายที่จะยิงเท้าของคุณด้วย C ++ -> บางอย่างของงูหลามสามารถใช้งานได้ ตอนนี้ฉันอยากจะทำงานใน C ++ ...
MrFox

1
@suslik: ว้าวฉันตกใจที่ทุกคนใช้ python กับระบบแบบนั้น ฉันเห็นด้วยกับคุณเกี่ยวกับรหัส noob หลาม noob; ฉันเห็นตัวเองแล้ว
Larry Coleman

13

มีเหตุผลในการใช้ C ++ หรือไม่ อย่างแน่นอน

บางคนอาจชอบใช้ C ++ มากกว่าตัวเลือกอื่น ๆ การถามว่ามีเหตุผลที่จะใช้ C ++ เหมือนการถามว่าทำไมเราต้องมีไอศกรีมหลายร้อยรสชาติ ทุกคนไม่ชอบเพียงแค่ติดกับวานิลลา

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

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


12

ฉันแค่เปลี่ยนจาก C เป็น C ++ และฉันคิดว่ากำไรเป็นสิ่งสำคัญแม้ว่าคุณจะไม่ต้องการเทมเพลตและ OOP ก็ตาม

  • การจัดการหน่วยความจำที่ดีขึ้น
  • ระบบประเภทที่แข็งแกร่ง
  • ห้องสมุดมาตรฐานที่ดีกว่า
  • namespaces
  • เป็นต้น

8

ฉันประหลาดใจที่ยังไม่มีใครพูดถึงเรื่องนี้ แต่ C ++ แนะนำเราให้อ้างอิงซึ่งเกือบจะแก้ปัญหาและข้อผิดพลาดของพอยน์เตอร์:

void ModifyVar(int& var)
{
    var = 5;
}

int test = 4;
ModifyVar(test);

แทน:

void ModifyVar(int * var)
{
    *var = 5;
}

int test = 4;
ModifyVar(&test);

ปลอดภัยกว่าและง่ายกว่าเช่นกัน ... และไม่มีค่าใช้จ่ายในการผ่านค่า


3
มีความยืดหยุ่นน้อยกว่ามาก การอ้างอิง (สไตล์ C ++) เป็นสิ่งที่ดีในการทำให้โครงสร้างทั่วไปบางอย่างง่ายขึ้นในภาษาที่มีพอยน์เตอร์อยู่ด้วย และตัวอย่างของคุณไม่ได้เป็นกรณีที่ดีสำหรับการอ้างอิง
Ben Voigt

3
@Ben: คุณช่วยอธิบายได้ไหมว่าทำไมมันถึงเป็นตัวอย่างที่ไม่ดี?
Nathan Osman

6
@ George: เพราะไม่มีอะไรเปลี่ยนแปลงยกเว้นว่าตัวละครสองตัว (นับ 'em) สั้นลง? มันไม่ได้แก้ปัญหาใด ๆ มันไม่ได้เน้นถึงข้อผิดพลาดใด ๆ มันไม่ได้ทำอะไรเจ๋ง ๆ เหมือนยืดอายุการใช้งานของตัวแปรชั่วคราว (ซึ่งการอ้างอิงที่ดี)
Ben Voigt

@Ben: คุณลืมบางสิ่งบางอย่าง - การอ้างอิงถูกต้องเสมอ พอยน์เตอร์สามารถชี้ไปที่สิ่งใดก็ได้ (รวมถึง NULL) ซึ่งสามารถนำไปสู่ข้อผิดพลาดหน่วยความจำทุกชนิดหากสิ่งไม่ถูกต้อง การอ้างอิงไม่สามารถเป็นค่า NULL และที่อยู่ที่ชี้ไปไม่สามารถเปลี่ยนแปลงได้
Nathan Osman

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

5

ที่ไหนและทำไมมักจะเป็น:

  • ความคุ้นเคย
  • คุณสมบัติภาษาที่ต้องการ
  • ไลบรารีเฉพาะที่คุณต้องการใช้
  • ต้องการประสิทธิภาพการทำงาน

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

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


2
ความคุ้นเคยเป็นเหตุผลข้อที่ 1 และฉันประหลาดใจที่คุณเป็นคนแรกที่พูดถึงมัน
Paul Butcher

4

C ++ กับ Python และ Perl ไม่สามารถตัดสินได้อย่างง่ายดาย ขึ้นอยู่กับโครงการและข้อกำหนด

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

C ++ ในอีกด้านหนึ่งมีข้อตกลงที่น่ากลัวเกี่ยวกับการพึ่งพาไลบรารี เมื่อคุณรวบรวมบางสิ่งใน GCC X หรือ VC ++ Y คุณจะไม่สามารถเชื่อถือได้ว่าโค้ดจะทำงานด้วยเครื่องมือรุ่นถัดไป นรกเดียวกันอยู่บน Windows และนรกเดียวกันก็อยู่ใน Unix ด้วย

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

Python นั้นง่ายยืดหยุ่นและเป็นภาษาไดนามิก ง่ายมากที่คุณสามารถส่งจำนวนเต็มไปยังฟังก์ชันสคริปต์คาดหวังสตริง แต่คุณสามารถได้ผลลัพธ์! แม้ว่าไม่คาดคิด แต่เป็นผลลัพธ์ ดังนั้นโปรแกรมเมอร์จึงต้องระมัดระวังเป็นอย่างยิ่ง IDLEเสนอการแก้ไขข้อบกพร่องบางอย่าง แต่เมื่อคุณได้ TELNET'ed กับระบบหรือ SSH'ed ในสามระดับและคุณต้องการค้นหาปัญหาของคุณดีบักเกอร์จะไม่อยู่เคียงข้างคุณ แต่มันสามารถทำงานทางคณิตศาสตร์ที่ยอดเยี่ยมได้อย่างรวดเร็ว

Java เป็นระบบนิเวศของ buzzwords เทคโนโลยีของมนุษย์ต่างดาวและคำใหญ่และเมื่อคุณต้องการเพียงแค่อัปโหลดไฟล์ไปยังเว็บเซิร์ฟเวอร์ที่คุณพบว่าคุณสามารถทำมันได้เฉพาะในกรณีที่เซิร์ฟเวอร์ที่มีJSP หากคุณต้องการเรียกไลบรารีระบบหรือฟังก์ชั่นระบบเช่นการตรวจสอบคุณพบว่าคุณต้องขุดมาก และบางทีอาจถึงJNIและตกลง ... คุณคิดว่า ... "ทำไมพระเจ้า"

นอกเหนือจากนั้น Java เป็นเครื่องมือที่ยอดเยี่ยมสำหรับห้องชุดธุรกิจและมัลติเธรดฉันชอบมันมาก

รวดเร็วในการจัดทำโปรแกรมและแสดงประวัติย่อของคุณ "โอ้ฉันรู้ว่าเทคโนโลยีเช่นกัน" และหัวหน้าที่คุณอยากจะประหลาดใจ! แม้ว่าเทคโนโลยีอาจจะไม่จำเป็นต้องใช้ ... (โอเค, คนฉันเกลียดSpring Framework .... )


1
อนึ่งคุณต้องพิจารณาว่า Python มีการอ้างอิงรุ่น - โดยเฉพาะอย่างยิ่งเมื่อคุณย้ายไปยัง Python 3 เหมือนกันกับ perl .. หรือมีใครสนใจที่จะย้ายไปที่ Perl 6 หรือยัง ทุกอย่างมีการพึ่งพาที่น่ารังเกียจ :(
gbjbaanb

3

สิ่งที่คุณควรคำนึงถึงในขณะที่เลือกภาษาคือสิ่งที่คุณจะได้รับจากการใช้และประโยชน์ที่จะได้รับ

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

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

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

วิธีแก้ปัญหานี้คือการใช้ภาษาที่ง่ายขึ้น (โดยง่ายขึ้นฉันหมายถึงนักพัฒนาที่เป็นมิตรมากขึ้น: พิมพ์น้อยลง, การตีความที่ขี้เกียจ, กิจวัตรและสิ่งที่มีมาก่อนอื่น ๆ มากมาย) เพื่อทำโค้ดของคุณทั้งหมด

คุณจะทำมันเร็วกว่าถ้าคุณทำกับ C หรือ C ++ มันจะทำให้ปวดสมองมากขึ้น

โปรแกรมของคุณจะช้า แต่ด้วย profiler คุณแยกส่วนที่วิ่ง 80% ของเวลาและคุณทำด้วย C หรือ C ++

ด้วยการ prorgamming ด้วยวิธีนี้คุณประหยัดเวลาได้มากและโปรแกรมของคุณมีประสิทธิภาพรวดเร็วมากมีโอกาสน้อยที่จะรั่วไหลความจำและคุณประหยัดเวลา

ภาษาสคริปต์ได้รับการออกแบบให้อยู่ด้านข้างของนักพัฒนา แต่การเพิ่มประสิทธิภาพยังคงเป็นไปได้ แน่นอนว่าคุณสามารถเป็นนักออกแบบลวดลายหรือวูดู STL หรือแม้แต่นักรบที่กระฉับกระเฉงและอาจเป็นพระฮาสเคลล์ แต่ภาษาทำให้เราพูดคุยกับคอมพิวเตอร์ภาษาไม่ได้ถูกสร้างขึ้นมาเพื่อให้เราเป็นคอมพิวเตอร์!



2

C ++ ที่ฉันใช้เรียกว่า C พร้อมคลาส!


8
ไชโยคุณใช้คำหลัก 'คลาส' ตอนนี้คุณเข้าใจการออกแบบ OO!
dss539

C ++ ของฉันเรียกว่า C พร้อมเนมสเปซ
jsz

6
C ++ ของฉันถูกเรียกว่าอืมมมม ..
Manoj R

+1 คลาสเป็นเหตุผลเดียวที่ฉันใช้ C ++
mbq

... ตกลงมีข้อยกเว้นด้วย
mbq

0

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

(แต่หลังจาก Haskell มาถึงก็ไม่มีเหตุผลที่จะใช้สิ่งอื่น)


0

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

อย่างไรก็ตามฉันจะไม่ใช้ Python, Perl ฯลฯ เพื่อหลีกเลี่ยงการใช้ C การตั้งค่าของฉันคือ C # จริง ๆ เพราะฉันชอบไลบรารี่ที่ดี (ซึ่งเป็นจุดแข็งของ. NET) และฉันชอบภาษาที่พิมพ์แบบคงที่ Booเป็นทางเลือกที่ดี แต่จริงๆแล้วHaskell , OCaml , D , MLและทั้งหมดนั้นก็ดี


7
คุณพลาดจุด
Matt Joiner

@ Matt Joiner: ฉันแน่ใจว่าฉันยังไม่ได้ ฉันพลาดอะไร?

คำถามเกี่ยวกับการไม่ใช้ C ++
Matt Joiner

@ Matt Joiner: อืมมมมมมฉันจะเห็นว่าถูกถาม แต่ดูเหมือนว่าฉันตอบว่าเกินไป (ฉันบอกว่าไม่รำคาญและทางเลือกที่ฉันใช้)

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