Khi nào nên sử dụng C trên C ++ và C ++ trên C?


164

Tôi đã được giới thiệu về Khoa học Máy tính được hơn một năm nay và theo kinh nghiệm của tôi, dường như cả C và C ++ đều được coi là ngôn ngữ "cực nhanh", trong khi các ngôn ngữ khác như Python và các ngôn ngữ kịch bản như vậy thường được coi là hơi chậm .

Nhưng tôi cũng đã thấy nhiều trường hợp trong đó một dự án phần mềm hoặc thậm chí một dự án nhỏ sẽ xen kẽ các tệp trong đó một số n nhất định của các tệp đó sẽ được viết bằng C và một số m nhất định của các tệp đó sẽ được viết bằng C ++.

(Tôi cũng nhận thấy rằng các tệp C ++ hầu như luôn có các tiêu đề tương ứng, trong khi các tệp C không quá nhiều). Nhưng quan điểm chính của tôi là tìm hiểu trực giác chung khi nào nên sử dụng C trên C ++ và khi nào nên sử dụng C ++ hơn C. Khác với thực tế là (1) C ++ là hướng đối tượng trong khi C thì không, và (2) các cú pháp rất giống nhau và C ++ được tạo ra một cách có chủ ý để giống với C theo nhiều cách, tôi không chắc sự khác biệt của chúng là gì. Dường như với tôi rằng chúng (gần như) có thể hoán đổi cho nhau trong nhiều lĩnh vực.

Vì vậy, nó sẽ được đánh giá cao nếu ai đó có thể làm sáng tỏ tình hình! Cảm ơn


4
Sử dụng C inline trong mã C ++ thường dành cho một số mô-đun nhất định cần được tối ưu hóa cao, thực hiện công việc ở mức độ thấp gần với phần cứng hoặc rất quan trọng đối với tính toàn vẹn của dữ liệu hoặc thậm chí là an toàn cho con người và cần phải được kiểm chứng và chứng minh chính xác. Thay vì thực hiện tất cả bằng C, phần lớn dự án có thể tận dụng các tính năng của C ++ cho các thiết kế linh hoạt, đồng thời nhận được lợi ích của sự chặt chẽ của C ở những nơi cần thiết.
kylben

30
@kylben: Nhiều anh chàng C ++ sẽ nói với bạn: (1) Hiệu suất không phải là lý do để giảm xuống C (có lẽ để tránh virtualvà một vài tính năng khác ngăn chặn tối ưu hóa, nhưng ví dụ, các virtuallớp không vốn không hiệu quả và các mẫu là một công cụ mạnh mẽ trừu tượng mà thực sự có thể dẫn đến nhiều hiệu quả - ví dụ qsortvs std::sort). (2) Tầm quan trọng cao của tính đúng đắn là một lý do để sử dụng C ++ (loại an toàn, constkhông, privateRAII để quản lý tài nguyên có thể quản lý được, v.v.) trên C. Hoặc vì vấn đề đó, hãy sử dụng Ada hoặc thứ gì đó ngay từ đầu.

11
@ Pubby8 Tôi không đồng ý với điều này. Nếu tôi đang làm việc trên một tệp .c và tôi thấy mọi người làm điều này, tôi có xu hướng đánh dấu họ về mặt tinh thần là không biết họ đang làm gì. Ví dụ: không cần phải chuyển từ void*loại con trỏ khác trong mã C, điều này rất gây mất tập trung và điển hình cho những người không biết C.
asveikau

4
@kylben: (Bạn có thể muốn học cách giải quyết chính xác những người khác trong câu trả lời nhận xét của mình, để họ có cơ hội thực sự nhìn thấy họ.) Rằng "một lập trình viên rất quen thuộc với cách trình biên dịch biến C thành asm" sẽ hoạt động như C ++ tốt. Nhưng điều đó chỉ đơn giản là không liên quan: Nếu bạn muốn tìm hiểu về asm, chỉ cần viết asm thay vì có một trình biên dịch tạo nó từ một số ngôn ngữ khác. Rốt cuộc, cách nó có thể thay đổi với mỗi bản cập nhật trình biên dịch.
sbi

9
Theo ý kiến ​​khiêm tốn của tôi ... bạn sử dụng C khi bạn muốn, đối với tôi: C đơn giản và dễ sử dụng hơn nhiều so với C ++ ... C ++ có thể trông giống như một "C With class", nhưng giờ thì không còn nữa một ngôn ngữ rất phức tạp, với những thứ như Trình xây dựng ảo và Mẫu.
Fraoco

Câu trả lời:


184

Bạn chọn C khi

  • bạn cần trình biên dịch di động (thực sự là C)
  • nền tảng của bạn không cung cấp C ++ (trình biên dịch C dễ thực hiện hơn nhiều),
  • bạn cần tương tác với các ngôn ngữ khác chỉ có thể tương tác với C (thường là mẫu số chung thấp nhất trên bất kỳ nền tảng nào) và mã của bạn bao gồm ít hơn giao diện, không đáng để đặt giao diện C qua mã C ++,
  • bạn hack trong một dự án nguồn mở (nhiều trong số đó, vì nhiều lý do , dính vào C),
  • bạn không biết C ++.

Trong tất cả các trường hợp khác, bạn nên chọn C ++.


15
Tôi cũng sẽ thêm rằng C ++ với mô hình ngoại lệ đôi khi mang lại nhiều rắc rối hơn giá trị của nó, ví dụ, hạt nhân OS. Ít nhất đó là cảm giác chung mà tôi có được khi đọc về các thứ.
Coder

12
@SF: C là ngôn ngữ chung? Đó là mới. Hay đúng hơn, rất cũ. Có thể nếu bạn chỉ trò chuyện với những người không học ngôn ngữ mới trong 20 năm qua, nhưng tôi nói rằng kiến ​​thức C không còn phổ biến nữa.
DeadMG

13
@SF.: Như tôi đã viết ở nơi khác, tôi đã tham gia vào các dự án lên tới hàng triệu LoC và thấy rất ít công cụ meta so với các dự án C với các vụ hack macro không thể tránh khỏi và có mặt khắp nơi. (OTOH, khả năng tạo EDSL khi cần có thể là một công cụ cực kỳ mạnh mẽ trong hộp của bạn.) Đối với C là ngôn ngữ chung: Tôi muốn nói theo thuật ngữ của tôi rằng đó là mẫu số chung thấp nhất. Và tôi sẽ không muốn những người có kỹ năng lập trình vừa phải hack vào nhân hệ điều hành.
sbi

18
@Max: Tôi hoàn toàn không đồng ý. C là một ngôn ngữ vô dụng, trừ khi một số rào cản thực tế không thể vượt qua ngăn cản việc sử dụng C ++.
DeadMG

17
@Buttons: Chính bạn là người đưa ra yêu cầu ("C ++ cần thêm bộ nhớ"), vì vậy chính bạn là người ủng hộ điều đó. Và, không, tôi không khẳng định rằng C ++ cần ít bộ nhớ hơn . Điều tôi đang nói là các tính năng có giá, bất kể trình biên dịch thực hiện chúng cho bạn (các hàm ảo) hay bạn tự làm chúng (mảng các con trỏ hàm).
sbi

88

Có một vài lý do để thích C. Lý do chính là nó có xu hướng khó sản xuất các tệp thực thi nhỏ hơn với C ++. Đối với các hệ thống thực sự nhỏ, dù sao bạn cũng hiếm khi viết nhiều mã và không gian ROM bổ sung cần thiết cho C ++ thay vì C có thể là đáng kể.

Tuy nhiên, tôi cũng nên nói thêm rằng đối với các hệ thống thực sự nhỏ, C có vấn đề với cùng một lý do và ngôn ngữ lắp ráp gần như là sự lựa chọn hợp lý duy nhất. Phạm vi kích thước hệ thống trong đó C thực sự có ý nghĩa là khá nhỏ và co lại liên tục (mặc dù tôi sẽ thừa nhận, khá chậm).

Một thời gian / lý do khác để sử dụng C là cung cấp một tập hợp các hàm mà bạn có thể liên kết với từ bất kỳ ngôn ngữ nào khác. Bạn có thể viết các hàm này trong C ++ bằng cách định nghĩa chúng là các extern "C"hàm, nhưng làm như vậy sẽ hạn chế các hàm đó để hiển thị "khuôn mặt" C-life cho thế giới - các lớp, hàm quá tải, mẫu và hàm thành viên, v.v., không cần ứng dụng. Tuy nhiên, điều này không nhất thiết hạn chế sự phát triển đối với C - hoàn toàn hợp lý khi sử dụng bất kỳ và tất cả các tính năng của C ++ trong nội bộ , miễn là giao diện bên ngoài trông giống như C.

Đồng thời, tôi phải nói rằng các câu trả lời của @ Toll (cho một ví dụ rõ ràng) có những điều gần như ngược về hầu hết các khía cạnh. C ++ được viết một cách hợp lý thường sẽ nhanh nhất bằng C, và thường nhanh hơn ít nhất một chút. Khả năng đọc nói chung tốt hơn nhiều, nếu chỉ vì bạn không bị vùi lấp trong tất cả các mã cho các thuật toán và cấu trúc dữ liệu tầm thường nhất, tất cả các xử lý lỗi, v.v.

Các mẫu không "khắc phục sự cố với hệ thống loại ngôn ngữ", chúng chỉ cần thêm một số khả năng cơ bản gần như hoàn toàn không có trong C và / hoặc C ++ mà không có mẫu. Một trong những ý định ban đầu là cung cấp cho các loại container an toàn, nhưng trên thực tế, chúng vượt xa điều đó - về cơ bản không có loại C nào cung cấp cả.

Các công cụ tự động cũng chủ yếu là một cá trích đỏ - trong khi sự thật là viết một trình phân tích cú pháp C ít công việc hơn so với viết một trình phân tích cú pháp C ++, nhưng thực tế là nó hầu như không có sự khác biệt cuối cùng. Rất ít người sẵn sàng hoặc có thể viết một trình phân tích cú pháp có thể sử dụng cho một trong hai. Như vậy, điểm khởi đầu hợp lý là Clang.

Khi điều đó xảy ra, C và C ++ được sử dụng khá thường xuyên cùng nhau trên cùng một dự án, được duy trì bởi cùng một người. Điều này cho phép một cái gì đó khá hiếm: một nghiên cứu so sánh trực tiếp, khách quan so sánh khả năng duy trì của mã được viết bằng hai ngôn ngữ bởi những người có thẩm quyền chung như nhau (nghĩa là cùng một người). Ít nhất trong nghiên cứu được liên kết, một kết luận đã rõ ràng và không mơ hồ: "Chúng tôi thấy rằng việc sử dụng C ++ thay vì C dẫn đến chất lượng phần mềm được cải thiện và giảm nỗ lực bảo trì ..."


12
Công cụ hỗ trợ không phải là cá trích đỏ. Cấp, ngày nay chúng ta có tiếng kêu. Nhưng công cụ hỗ trợ cho C ++ không bị tụt hậu so với các ngôn ngữ oder đáng kể, ngay cả trong các IDE lớn. Tại sao vậy? Đơn giản, vì cho đến gần đây không có tiếng kêu (và GCC không bao giờ là một sự thay thế). Cho đến khoảng nửa năm trước, nếu bạn cần mã AST của C ++, về cơ bản bạn đã hết may mắn hoặc hết hàng ngàn đô la (nếu bạn mua giao diện EDG).
Konrad Rudolph

5
+1 và để ghi lại, tôi thường xuyên viết mã C ++ cho bộ xử lý 8 bit với ROM 4KiB.
avakar

2
+1 cho một câu trả lời tuyệt vời tổng thể. Điều tôi không hiểu (tôi không có kinh nghiệm về việc này) là tại sao (tôi đoán chúng ta đang nói chuyện được nhúng?) Một trình biên dịch C sẽ tạo ra mã thực thi nhỏ hơn trình biên dịch C ++ được cung cấp cùng bộ tính năng được sử dụng ? Có lẽ bạn có thể cung cấp một số tài liệu tham khảo?
Martin Ba

2
@Martin: điều chính là C ++ bao gồm xử lý ngoại lệ, mà (ít nhất là thường xuyên) thêm một số tối thiểu vào kích thước thực thi. Hầu hết các trình biên dịch sẽ cho phép bạn vô hiệu hóa xử lý ngoại lệ, nhưng khi bạn thực hiện thì kết quả không còn là C ++ nữa. Tôi nghi ngờ cũng có một chút từ thực tế đơn giản là nhiều nhà cung cấp trình biên dịch C ++ không làm việc hết sức trong việc tạo mã đầu ra nhỏ nhất có thể.
Jerry Coffin

3
"Chúng tôi thấy rằng việc sử dụng C ++ thay vì C dẫn đến chất lượng phần mềm được cải thiện và giảm nỗ lực bảo trì ..." đó là kết luận cần nhớ.
Stephane Rolland

24

Sự khác biệt giữa C và C ++ đã được liệt kê chi tiết ở đây . Mặc dù đôi khi mọi người có thể có lý do chính đáng để chọn cái này hoặc cái kia (C ++ cho OOP hoặc C khi họ cảm thấy các tính năng bổ sung của C ++ giới thiệu chi phí không mong muốn, chẳng hạn), theo kinh nghiệm của tôi, nó thường chỉ được ưu tiên. Những người làm việc trên tập tin này biết gì hơn và thích tốt hơn? Tôi tin rằng đây là lý do hầu hết thời gian, vì sự thật là các ngôn ngữ này đều giải quyết các ứng dụng quan trọng về hiệu năng.

(Lưu ý bên lề: Hãy xem Linus Torvads nói về lý do tại sao anh ấy thích C hơn C ++. Tôi không nhất thiết phải đồng ý với quan điểm của anh ấy, nhưng nó cho bạn cái nhìn sâu sắc về lý do tại sao mọi người có thể chọn C hơn C ++. có thể chọn C vì những lý do này.)


51
-1cho lời ca ngợi của Linus. : - {
sbi

12
Đừng trừ tôi vì điều đó! Haha. Tôi không đồng ý với Linus, nhưng đó là một ví dụ khá hay về lý do TẠI SAO mọi người có thể chọn C hơn C ++ (nếu họ tin những gì Linus tin). Tôi không bình luận về tính hợp pháp của những lý do đó.
Casey Patton

10
@CaseyPatton: Về cơ bản, tôi đánh giá thấp mọi câu trả lời trình bày lời nói hoa mỹ này không bị làm phiền như thể đó là một cuộc tranh luận thực sự.
sbi

11
@Coder: Bạn hoàn toàn không cần biết triển khai STL. Điểm chính của STL là bạn không cần phải biết việc triển khai, trừ khi bạn dựa vào hành vi không được xác định bởi Tiêu chuẩn - trong trường hợp nào, tại sao phải sử dụng thư viện Chuẩn? Hơn nữa, nó không hơn một chút điên rồ khi không thích một ngôn ngữ vì cách các nhà phát triển hành xử. Các lập trình viên C hành xử như C là món quà của Chúa dành cho con người và quá mù quáng khi thấy sự thật hiển nhiên rằng C ++ cung cấp các tính năng vượt trội về cơ bản và trực tiếp so với C, như RAII.
DeadMG

8
@Coder: Nếu bạn kết thúc với quá nhiều shared_ptrs cho một đối tượng mà bạn tràn bộ đếm nội bộ, bạn đã làm sai. Tiêu chuẩn sẽ chỉ định kích thước tối thiểu cho bộ đếm - có thể là 32 bit - và thật phi thực tế khi phải có hơn 2 tỷ shared_ptrs cho một đối tượng. Ngay cả khi bản thân đối tượng có kích thước 0 và bạn có bộ cấp phát bộ nhớ trên không, thì bạn vẫn tiêu thụ 16GB bộ nhớ, chỉ trên shared_ptrs.
DeadMG

13

Vấn đề chính còn thiếu trong các câu trả lời hiện có (tính đến thời điểm đăng bài này) là sự lựa chọn.

Thật đơn giản. Nếu, vì một số lý do hoàn toàn phi lý, bạn cảm thấy rằng các ngoại lệ không đáng giá, thì bạn không phải sử dụng chúng . Bạn vẫn có thể có các mẫu và RAII và thư viện Chuẩn và không bao giờ viết một "cú ném" duy nhất. Các mẫu cũng vậy. Nếu, vì một số lý do, bạn cảm thấy chúng gây ra không thể hủy ngang (và thực sự quan trọng, chỉ có trên phần mềm thực thi được nhúng), thì thật bất ngờ - bạn cũng có thể sử dụng void * và sizeof (T) cả ngày. Không có gì buộc bạn phải sử dụng bất kỳ tính năng C ++ nào trên C.

Đó là lý do tại sao C ++ là một ngôn ngữ ưu việt vốn có - bạn có thể chọn các tính năng bạn muốn và quay lại lập trình kiểu C khi bạn không thích một tính năng nhất định. Do đó, cho rằng C ++ là tất cả mọi thứ của C và hơn thế nữa, có một sự thật hiển nhiên rằng C ++ là một ngôn ngữ ưu việt. Gợi ý khác giống như cố gắng gợi ý rằng 4 lớn hơn 5.


1
Theo lý luận của bạn, không có điểm nào trong câu hỏi ban đầu và do đó nó nên được đóng lại. Tôi đoán câu hỏi nên được đọc một cái gì đó như: khi nào chúng ta nên giới hạn bản thân trong tập con C của C ++ (sử dụng C đơn giản) và khi nào thì nên sử dụng C ++ đầy đủ.
Giorgio

Điều này là đúng, nhưng chỉ đối với trường hợp một người làm việc trong dự án nhỏ của riêng họ. Trong cuộc sống thực, hầu hết mọi người đều dành một nửa thời gian để làm việc với mã của người khác. Thật không may, hầu hết những người khác "nghĩ sai" về những lý do hoàn toàn phi lý đó.
DarenW

1
@DeadMG: Làm thế nào các nhà phân phối có nghĩa là báo cáo lỗi mà không ném ngoại lệ? Ngoài ra, việc thêm nhiều tính năng không nhất thiết phải tốt hơn khi tất cả những gì nó làm là thêm độ phức tạp hoặc dự phòng.
Mankude

@Mankude: Nếu bạn biên dịch với các tùy chọn để vô hiệu hóa ngoại lệ, người cấp phát sẽ hủy bỏ chương trình hoặc vui vẻ tiến hành sử dụng con trỏ null, tùy thuộc vào việc triển khai thư viện.
Zan Lynx

4
@Mankude: Vì kinh nghiệm của tôi vào năm 2007 khi tôi thử chạy hệ thống Linux với RAM 1 GB và không có trao đổi, hầu như tất cả các phần mềm máy tính để bàn đều thất bại theo những cách khủng khiếp khủng khiếp khi việc cấp phát bộ nhớ không thành công.
Zan Lynx

9

Những điều về C ++ khiến các lập trình viên C lo lắng

Có rất nhiều phép thuật xảy ra dưới mui xe; hàm tạo, hàm hủy, phương thức ảo, mẫu, v.v., có thể làm cho mã C ++ dễ viết và nhanh hơn rất nhiều so với mã C tương đương, nhưng khó hiểu và lý do hơn (tùy thuộc vào mức độ bạn biết C ++ và các quy ước liên quan của nó). Một cái gì đó đơn giản như Foo newFoo;có thể gọi rất nhiều mã, tùy thuộc vào cách xây dựng cho lớp Foo(và bất kỳ lớp nào mà nó phụ thuộc) đã được xác định. Đây cũng là lý do tại sao quy ước là viết ++itthay vì it++khi lặp qua một container, vì postfix ++thường liên quan đến một hoạt động sao chép đắt tiền.

Tùy thuộc vào những gì bạn đang làm, có thể có một số chi phí không hề nhỏ, đặc biệt là đối với các tác vụ đơn giản. Lấy hai chương trình sau, chương trình thứ nhất trong C, chương trình thứ hai trong 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 */

Hành vi giống hệt nhau, không có nhiều sự khác biệt về nguồn, nhưng trên hộp SLES 10 tôi làm việc với gcc 4.1.2, cái trước tạo ra một kích cỡ ~ 9kb, trong khi cái thứ hai chiếm hơn 12,5kb (không tối ưu hóa ), lớn hơn gần 28%. Kiểu C ++ stringhoạt động với IMO dễ dàng hơn rất nhiều so với thư viện chuỗi C và các luồng C ++ linh hoạt và tùy biến hơn rất nhiều so với các luồng C, nhưng đối với mã thực sự hại não như thế này, chúng có thể không đáng giá.

C ++ là một ngôn ngữ khổng lồ so với C, với một số ngữ nghĩa cực kỳ phức tạp. Mất nhiều thời gian hơn để thành thạo C ++ hơn C, có nghĩa là nhiều người tuyên bố biết C ++ không biết điều đó cũng như họ nghĩ họ làm.

Những điều về C khiến các lập trình viên C ++ lo lắng

C không phải là một ngôn ngữ lập trình an toàn bởi bất kỳ sự tưởng tượng nào; không có giới hạn kiểm tra trên các mảng dẫn đến nhiều hành vi có thể khai thác (có thể thông qua getschức năng đã chết hoặc thông qua scanfcác chỉ định %s%[chuyển đổi). C ++ ít nhất cung cấp cho bạn các thùng chứa ngoại lệ nếu bạn cố truy cập bên ngoài phạm vi được xác định hiện tại của chúng; tất cả C cung cấp cho bạn là (nếu bạn may mắn) vi phạm phân khúc.

Quản lý bộ nhớ trong C rất tốn nhiều công sức và dễ bị lỗi, so với các công cụ mà C ++ cung cấp cho bạn. Nếu bạn đang xây dựng vùng chứa của riêng mình, bạn có trách nhiệm đối chiếu tất cả các cuộc gọi mallocfreecuộc gọi, đảm bảo phân bổ thành công, sao lưu mọi phân bổ một phần trong trường hợp xảy ra lỗi, v.v. Trong C ++, bạn chỉ cần thêm các mục vào hoặc loại bỏ các mục từ container. Nếu có vấn đề, một ngoại lệ sẽ được đưa ra.

Tương tự, xử lý lỗi trong C là một nỗi đau ở mông so với các công cụ mà C ++ cung cấp (cụ thể là các ngoại lệ). Điều thực sự thú vị là khi bạn phân bổ một loạt bộ nhớ và sau đó đập vào tường trong quá trình xử lý của bạn; khi bạn phải thoát ra, bạn phải giải phóng bộ nhớ đó theo đúng thứ tự. Với các nguyên tắc C ++ và RAII, điều này (tương đối) dễ thực hiện.

Vì vậy, khi nào tôi sử dụng cái này hơn cái kia?

Nếu những gì bạn viết là đơn giản, hãy đọc nó / muck với nó / thoát khỏi ứng dụng, hành vi của chúng có thể được mô tả rõ ràng về mặt đầu vào và đầu ra, vấn đề hiệu suất, sau đó thích C hơn C ++. Nếu không, thích C ++


2
Quản lý bộ nhớ rất phức tạp và dễ bị lỗi trong một số trường hợp, nhưng đặc biệt là trong thế giới nhúng, việc viết chương trình C bằng cách sử dụng cấp phát bộ nhớ tĩnh hoàn toàn thực tế. Nếu chương trình liên kết, nó không thể hết bộ nhớ khi chạy. Những đảm bảo như vậy có thể dễ dàng đạt được trong C ++ không?
supercat

9

Bjarne Stroustrup duy trì một danh sách các ứng dụng và công ty sử dụng C ++; bạn có thể tranh luận về lập trình thủ tục so với lập trình OOP tất cả những gì bạn muốn, nhưng bạn không thể tranh luận với kết quả của ngành trong 20 năm qua.

C ++ thường được sử dụng cho các dự án phức tạp, nhiều người, quy mô lớn, nơi những người riêng biệt cần làm việc trên các thành phần được mô đun hóa. Dĩ nhiên, bạn có thể xây dựng và duy trì mã được mô đun hóa trong C, nhưng bản chất OOP vốn có của C ++ dẫn đến mô đun hóa, khả năng kiểm tra và tái sử dụng mã vượt trội.

Thư viện chuẩn C ++ (STL), bản thân nó chỉ có vectơ và bản đồ, là lý do đủ để sử dụng C ++.

C thường được sử dụng cho các hệ thống nhúng.

Cá nhân tôi chỉ sử dụng C nếu có một số thư viện chỉ có API C.


19
Câu cuối cùng của bạn không phải là lý do để sử dụng C. Bạn có thể gọi các thư viện C từ C ++.
dùng207421

2
Tôi đã sử dụng c ++ cho một dự án DSP - không phải c
BЈовић

9

Tôi sẽ nói rằng lý do chính tại sao tôi chọn C hơn C ++, chỉ khi tôi phải dùng đến "Nó đã ổn định 1000%" loại công cụ của NASA.

C ++ là ~ 99% C khi chúng ta nhìn vào hiệu suất, và nó hiệu quả hơn rất nhiều. Vì vậy, ngay cả khi ở C, bạn có thể viết mã sẽ nhanh hơn C ++ (bạn có thể sử dụng tập hợp con của C ++ mà không có ngoại lệ, ảo, phát trực tuyến, trừu tượng, v.v., nhưng về cơ bản là C), thời gian để tối ưu hóa mọi thứ chết tiệt Trong khi STL đã được thử nghiệm và thực hiện điều đó, sẽ tốn kém hơn so với hiệu suất nhỏ mà bạn có thể đạt được hoặc hy sinh vì thuật toán STL đã được viết bởi các nhóm chuyên gia và có lẽ bạn không phải là chuyên gia về mọi thứ.

Mặt khác, C ++ có rất nhiều thứ trừu tượng. Khi trong hoàn cảnh họ bị rò rỉ, điều này khiến bạn gặp rắc rối. Và có rất ít người biết 100% C ++ gotchas, trong khi, tôi đoán, có nhiều người biết tất cả C gotchas, vì vậy việc viết một giải pháp trong đó mọi bước của mọi thành viên trong nhóm đều dễ hiểu hơn rất nhiều trong C.

Ví dụ: Bạn có biết khi nào shared_ptr<smthn>sẽ vượt quá số tham chiếu của nó, nó sẽ đưa ra một ngoại lệ? Những thứ như thế này không tuyệt vời khi Shuttle phải nhập lại bầu không khí, ít nhất là tôi đoán vậy.

Ngoài ra, xử lý ngoại lệ là rất, rất khó so với mã lỗi. Thật khó để xem liệu lớp học có ngoại lệ 100% an toàn hay không và dễ bị rò rỉ. Rất nhiều người đại diện cao đã bày tỏ ý kiến ​​này.


12
Và theo cách chính xác thì quản lý bộ nhớ "ổn định" hơn so với trừu tượng của C ++ như thế nào std::stringvà như thế nào? Bạn đã bao giờ thử chỉ định một nền tảng trong đó shared_ptrbộ đếm sẽ tràn? Đó sẽ là một trong những nền tảng hài hước. Và nếu bạn nghĩ rằng việc xử lý ngoại lệ là khó khăn, bạn nên xem xét một đoạn mã C để kiểm tra mọi lỗi có thể xảy ra trên mỗi lệnh gọi hàm. .
sbi

12
@Lundin: '"Việc triển khai phải ổn định 1000%" không cho phép cấp phát bộ nhớ động ngay từ đầu'. Và điều gì ngăn bạn làm điều đó chính xác trong C ++ ?? (Và đưa ra những tuyên bố về kiến ​​thức và kinh nghiệm của tôi thay vì cung cấp bất kỳ đối số nào là một thủ thuật tu từ khá rẻ.)
sbi

10
@Lundin: Thật tốt khi bạn đã bắt đầu cung cấp các đối số, thay vì hùng biện. Nhưng họ yếu đuối. Rằng bạn đã "quên" một trong những tính năng chính của C ++ (mẫu), một tính năng giúp mã an toàn hơn (vì nó cho phép thuật toán được thực thi - và do đó, thất bại - tại thời gian biên dịch , loại bỏ lỗi thời gian chạy), không nói theo hướng có lợi cho kiến ​​thức của bạn về ngôn ngữ mà bạn đang đánh giá. Việc giảm C ++ thành ngôn ngữ OO đã bị chỉ trích trước đây và vì những lý do chính đáng. (Bên cạnh đó, các lớp có sự phá hủy xác định là một công cụ tuyệt vời và hữu ích để quản lý các tài nguyên khác ngoài bộ nhớ.)
sbi

9
@Lundin Tất nhiên bạn sẽ không muốn sử dụng std::stringnếu bạn không muốn phân bổ động. Bạn sẽ sử dụng std::basic_string<char, std::char_traits<char>, some_allocator_here>.
Luc Danton

10
@Coder: Bạn nghĩ bạn chứng minh điều gì với những điều này? Mã đầu tiên đơn giản là mã xấu (và sẽ là lỗi báo cáo xấu như giá trị trả về), mã thứ hai tạo ra trường hợp cho RAII về việc dọn dẹp thủ công mà mọi nhà phát triển C ++ nửa vời sẽ vui mừng và Joel, nhiều như tôi tôn trọng anh ấy, đã nói một vài điều tôi rất không đồng ý. Đầu cắm của anh ta cho những lần xuất hiện một lần duy nhất thoát ra khỏi một cái rắm cũ không hiểu biết, người sẽ không bao giờ đồng ý rằng những gì anh ta học được 25 năm trước đã bị vượt qua. (Xin nhớ, tôi đã lập trình 25 năm trước, khi SESE là trạng thái của nghệ thuật.)
sbi

6

C là lắp ráp di động với cú pháp tốt hơn, mang lại cho người lập trình toàn quyền kiểm soát mọi thứ .

Mặt khác, C ++ có rất nhiều phép thuật thú vị (chức năng ảo, quá tải, chuyển đổi tự động, v.v.) có thể không được mong muốn khi bạn muốn chắc chắn rằng mình:

  • không sử dụng nhiều bộ nhớ hơn bạn muốn
  • không truy cập các trang bộ nhớ willy nilly (vtable có thể ở bất cứ đâu)
  • đừng vô tình gọi nhiều mã

Và muốn một cái gì đó thực sự đơn giản để làm việc, vì bạn tập trung vào hiệu suất.

Nó không có gì đáng ngạc nhiên, và điều đó rất có giá trị.

Nếu bạn muốn (và tôi khuyên bạn nên làm như vậy), hãy đọc hướng dẫn mã hóa JSF về những gì bạn cần suy nghĩ khi viết C ++ để kiểm soát hệ thống điện tử hàng không quân sự. Có rất nhiều bẫy trong đó bạn cần phải biết và nó có thể giúp bạn thoát ra. Bjarne là một phần của tài liệu đó, vì vậy anh ta biết nó là gì.

Ngoài ra, C biên dịch như một con troll bị bỏng do sét đánh. C ++, OTOH, có lẽ được tài trợ bởi chính những người đầu tư vào các công ty SSD. :)

(Cá nhân tôi cũng thích C ++ hơn, nhưng tôi cũng không thích nó ...... .-P)


1
Có rất nhiều thứ C không cung cấp quyền kiểm soát. Hãy thử viết mã di động hiệu quả để nhân uint32_t với uint32_t để mang lại kết quả uint32_t (32 bit dưới cùng của sản phẩm). Nếu một intlà 64 bit, người ta phải truyền ít nhất một toán hạng để uint64_tngăn chặn Hành vi không xác định, nhưng phải truyền tới 64 bit cho mục đích tính toán kết quả 32 bit - để nói một cách nhẹ nhàng - "đáng ngạc nhiên".
supercat

Không phải vậy. Trình biên dịch thực hiện những việc như phân bổ đăng ký cho bạn. Tôi không thể viết mã duy trì trong lắp ráp, trong CI có thể.
Nils

2

(cho bạn có sự quen thuộc như nhau với cả hai ngôn ngữ)

Đi với C ++ trừ khi không có trình biên dịch C ++ cho nền tảng của bạn. Bạn có thể viết mã C ++ mà không cần bất kỳ phần ngôn ngữ nào bạn không thích (không có lớp, ngoại lệ, thừa kế ảo, bất kỳ hạn chế cá nhân nào bạn muốn áp dụng), và sau đó vào một lúc nào đó trong tương lai, nếu bạn quyết định bạn muốn một số những tính năng đó sau khi tất cả, sau đó bạn có thể dễ dàng sử dụng chúng. Không có gì trong C ++ ngăn bạn viết mã kiểu C.

(được cung cấp bộ công cụ tương đương và kiến ​​thức dành cho nhà phát triển) Không có lý do để chọn C trên C ++ với điều kiện nền tảng của bạn có trình biên dịch C ++. Bạn có thể chỉ cần giới hạn bản thân trong tập hợp con của ngôn ngữ bạn muốn hôm nay, trong khi vẫn mở cửa để mở rộng sau này.


1

Cả hai ngôn ngữ đều tuyệt vời. Tôi nghĩ rằng một số áp phích đã nêu chi tiết các điểm mạnh và cách sử dụng khác nhau cho mỗi. Tôi chỉ đơn giản sẽ thêm điều này:

Tôi thấy ngôn ngữ C hoàn hảo ở 4 lĩnh vực: 1) Tôi nghĩ đó là ngôn ngữ tốt nhất để sử dụng khi lần đầu tiên học bất kỳ loại lập trình nào [kết hợp với một số hội và kiến ​​thức về mã máy], 2) thật tuyệt vời khi viết trình điều khiển, 3) phần mềm và 4) phần mềm hệ thống ở mức thấp nhất.

C ++ là một ngôn ngữ hướng đối tượng, nhưng nó cũng có thể là thủ tục (rất nhiều theo cách của C). Nếu bạn đang làm việc trên các dự án quy mô lớn, phần mềm dựa trên GUI, phần mềm chơi trò chơi và các loại phần mềm chuyên sâu về đồ họa khác, thì tôi thấy C ++, Java hoặc thậm chí là Objective-C là lựa chọn tốt nhất của bạn. Tuy nhiên, có rất nhiều chương trình dòng lệnh hoặc phần mềm hệ thống mà bạn có thể thấy C ++ tốt hơn hoặc tốt hơn C.


0

Theo tôi có một điểm còn thiếu trong cuộc thảo luận này: C đơn giản hơn khi cung cấp giao diện nhị phân ổn định từ thư viện. Cả hai để sử dụng với các ngôn ngữ khác cũng như C ++.

Trong C ++, các trình biên dịch khác nhau sử dụng cách xáo trộn tên khác nhau để người tiêu dùng của thư viện được biên dịch với trình biên dịch khác với thư viện có thể gặp sự cố khi sử dụng nó. Với C, giao diện nhị phân, thông thường, được chuẩn hóa cho nền tảng.

Tôi biết rằng các trình biên dịch ngày nay thường có các công tắc để tạo ra những thứ tương thích với gcc, nhưng điều đó không phải lúc nào cũng có ích.

Tôi quan sát điều này trên Solaris tương đối thường xuyên. Việc phân phối và các nhà cung cấp phần mềm khác nhau thường sử dụng Sun Studio, đặc biệt là trên các hệ thống Sparc, nó thường cung cấp kết quả tốt hơn. Các dự án nguồn mở Man được viết với mã gcc cụ thể mặc dù. Có thể khá đau đớn để có được những người làm việc cùng nhau.


0

C có lẽ thích hợp hơn C ++ khi mã C được tạo (ví dụ: trong việc triển khai các ngôn ngữ cấp cao hơn). Ví dụ: có một số trình biên dịch giống Lisp phát ra mã C (ví dụ Chicken , Scheme48 ...), nhưng tôi không biết trình biên dịch nào phát ra mã C ++ chính hãng ( công cụ MELT của tôi phát ra mã C ++, nhưng tôi sẽ không gọi mã đó là chính hãng Mã C ++, nó sử dụng rất ít tính năng C ++).

Mã C cũng dễ dàng hơn để chứng minh bán tự động. Các máy phân tích tĩnh như Frama-C (nơi bạn chú thích mã C của bạn với các nhận xét ACSL để giúp lý do của người cung cấp mã của bạn) có sẵn cho C, nhưng không nhiều cho C ++ 11 đầy đủ.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.