C ++ làm gì tốt hơn D?


135

Gần đây tôi đã học D và đang bắt đầu làm quen với ngôn ngữ này. Tôi biết những gì nó cung cấp, tôi chưa biết cách sử dụng mọi thứ và tôi không biết nhiều về thành ngữ D, v.v., nhưng tôi đang học.

Tôi thích D. Đó là một ngôn ngữ hay, theo một cách nào đó, một bản cập nhật lớn cho C, và được thực hiện độc đáo. Không có tính năng nào có vẻ như "bắt vít", nhưng thực sự khá chu đáo và được thiết kế tốt.

Bạn sẽ thường nghe rằng D là những gì C ++ nên có (Tôi để lại câu hỏi liệu điều đó có đúng với mỗi người và mọi người tự quyết định để tránh các cuộc chiến nảy lửa không cần thiết hay không). Tôi cũng đã nghe từ một số lập trình viên C ++ rằng họ thích D nhiều hơn C ++.

Chính tôi, trong khi tôi biết C, tôi không thể nói rằng tôi biết C ++. Tôi muốn nghe từ một người biết cả C ++ và D nếu họ nghĩ rằng có một thứ gì đó mà C ++ làm tốt hơn D như một ngôn ngữ (nghĩa là không phải thông thường "nó có nhiều thư viện của bên thứ ba" hoặc "có nhiều tài nguyên hơn" hoặc "có nhiều tài nguyên hơn" hoặc "có nhiều tài nguyên hơn" hoặc " nhiều công việc yêu cầu C ++ hơn D tồn tại ").

D được thiết kế bởi một số lập trình viên C ++ rất lành nghề ( Walter BrightAndrei Alexandrescu , với sự giúp đỡ của cộng đồng D) để khắc phục nhiều vấn đề mà C ++ gặp phải, nhưng rốt cuộc có điều gì thực sự không tốt hơn? Có gì anh nhớ? Một cái gì đó bạn nghĩ không phải là một giải pháp tốt hơn?

Ngoài ra, lưu ý rằng tôi đang nói về D 2.0 , không phải D 1.0 .


15
Tôi chắc chắn rằng cộng đồng D sẽ thấy điều này vì tôi chắc chắn có nhiều nhà phát triển C ++ hơn nhiều so với các nhà phát triển D ở đây. Bằng cách đó, bạn sẽ có câu trả lời thú vị hơn hoặc ít nhất là khác nhau.
Klaim

7
Ngoài ra, D2 được thiết kế bởi Walter Bright nhưng với Alexandrescu cũng vậy. Bạn có thể muốn sửa nó trong câu hỏi của bạn.
Klaim

2
@Klaim: đã có (và vẫn còn) rất nhiều sự tham gia của cộng đồng vào D và thư viện chuẩn.
Michal Minich

28
@Anto Là một ngôn ngữ, C ++ tốt hơn rất nhiều so với D trong việc khiến bạn, lập trình viên, ghét cuộc sống của bạn.
Arlen

6
@jokoon: Trên thực tế, vâng, với rất ít công việc: digitalmars.com/d/2.0/interfaceToC.html
Anto

Câu trả lời:


124

Hầu hết những thứ mà C ++ "làm" tốt hơn D là những thứ meta: C ++ có trình biên dịch tốt hơn, công cụ tốt hơn, thư viện trưởng thành hơn, nhiều ràng buộc hơn, nhiều chuyên gia hơn, nhiều hướng dẫn hơn, v.v ... Về cơ bản, nó có nhiều hơn và tốt hơn tất cả những thứ bên ngoài mà bạn sẽ mong đợi từ một ngôn ngữ trưởng thành hơn. Điều này là không thể chối cãi.

Đối với bản thân ngôn ngữ, có một vài điều mà C ++ làm tốt hơn D theo ý kiến ​​của tôi. Có lẽ có nhiều hơn, nhưng đây là một vài cái mà tôi có thể liệt kê ra khỏi đỉnh đầu của tôi:

C ++ có một hệ thống loại suy nghĩ tốt hơn
Hiện tại có khá nhiều vấn đề với hệ thống loại trong D, có vẻ như là quá khổ trong thiết kế. Ví dụ, hiện tại không thể sao chép một cấu trúc const sang một cấu trúc không phải là cấu trúc nếu cấu trúc chứa các tham chiếu hoặc con trỏ đối tượng lớp do tính chuyển đổi của const và cách các hàm tạo của postblit hoạt động trên các loại giá trị. Andrei nói rằng anh ta biết cách giải quyết vấn đề này, nhưng không đưa ra bất kỳ chi tiết nào. Vấn đề chắc chắn có thể khắc phục (giới thiệu các nhà xây dựng bản sao theo kiểu C ++ sẽ là một sửa chữa), nhưng hiện tại nó là một vấn đề lớn trong ngôn ngữ.

Một vấn đề khác đã làm tôi khó chịu là thiếu const const (nghĩa là không mutablegiống như trong C ++). Điều này rất tốt cho việc viết mã an toàn cho luồng, nhưng gây khó khăn (không thể?) Khi thực hiện việc định hướng lười biếng trong các đối tượng const (nghĩ về hàm const 'get' để xây dựng và lưu trữ giá trị được trả về trong cuộc gọi đầu tiên).

Cuối cùng, với những vấn đề tồn tại, tôi đang lo lắng về cách thức phần còn lại của hệ thống kiểu ( pure, shared, vv) sẽ tương tác với mọi thứ khác trong ngôn ngữ khi chúng được đưa vào sử dụng. Thư viện tiêu chuẩn (Phobos) hiện sử dụng rất ít hệ thống loại tiên tiến của D, vì vậy tôi nghĩ rằng đó là hợp lý cho câu hỏi liệu nó có giữ được căng thẳng hay không. Tôi hoài nghi, nhưng lạc quan.

Lưu ý rằng C ++ có một số loại mụn cóc hệ thống (ví dụ: không phải là transitive, iteratorcũng như yêu cầu const_iterator) làm cho nó khá xấu, nhưng trong khi hệ thống loại của C ++ có một chút sai ở các bộ phận, nó không ngăn bạn hoàn thành công việc như D đôi khi không.

Chỉnh sửa: Để làm rõ, tôi tin rằng C ++ có hệ thống loại suy nghĩ tốt hơn - không nhất thiết phải là hệ thống tốt hơn - nếu điều đó có ý nghĩa. Về cơ bản, trong DI cảm thấy rằng có một rủi ro liên quan đến việc sử dụng tất cả các khía cạnh của hệ thống loại của nó không có trong C ++.

D đôi khi hơi quá thuận tiện
Một lời chỉ trích mà bạn thường nghe về C ++ là nó ẩn một số vấn đề cấp thấp từ bạn, ví dụ như các bài tập đơn giản như a = b;có thể thực hiện nhiều việc như gọi toán tử chuyển đổi, gọi toán tử gán quá tải, v.v. khó nhìn từ mã. Một số người thích điều này, một số người thì không. Dù bằng cách nào, trong D nó là tồi tệ hơn (tốt hơn?) Do những thứ như opDispatch, @property, opApply, lazymà có khả năng thay đổi mã tìm kiếm vô tội vào những điều mà bạn không mong đợi.

Tôi không nghĩ rằng đây là một vấn đề lớn cá nhân, nhưng một số người có thể thấy điều này gây khó chịu.

D yêu cầu thu gom rác
Điều này có thể được xem là gây tranh cãi vì có thể chạy D mà không cần GC. Tuy nhiên, chỉ vì nó có thể không có nghĩa là nó thực tế. Nếu không có GC, bạn sẽ mất rất nhiều tính năng của D và sử dụng thư viện chuẩn sẽ giống như đi bộ trong một bãi mìn (ai biết chức năng nào phân bổ bộ nhớ?). Cá nhân, tôi nghĩ rằng việc sử dụng D mà không có GC là hoàn toàn không thực tế và nếu bạn không phải là người hâm mộ của các GC (như tôi) thì điều này có thể khá khó chịu.

Các định nghĩa mảng ngây thơ trong D cấp phát bộ nhớ
Đây là một tiểu thú cưng của tôi:

int[3] a = [1, 2, 3]; // in D, this allocates then copies
int a[3] = {1, 2, 3}; // in C++, this doesn't allocate

Rõ ràng, để tránh phân bổ trong D, bạn phải làm:

static const int[3] staticA = [1, 2, 3]; // in data segment
int[3] a = staticA; // non-allocating copy

Những phân bổ 'đằng sau lưng' của bạn là những ví dụ điển hình về hai điểm trước đây của tôi.

Chỉnh sửa: Lưu ý rằng đây là một vấn đề đã biết đang được xử lý.
Chỉnh sửa: Điều này hiện đã được sửa. Không phân bổ diễn ra.

Kết luận
Tôi đã tập trung vào những tiêu cực của D so với C ++ vì đó là những gì câu hỏi được hỏi, nhưng xin đừng xem bài đăng này là một tuyên bố rằng C ++ tốt hơn D. Tôi có thể dễ dàng tạo một bài đăng lớn hơn về những nơi mà D tốt hơn hơn C ++. Tùy thuộc vào bạn để đưa ra quyết định sử dụng cái nào.


Tôi đã nhìn D vài năm trước (trước 2.0). Bộ sưu tập rác không thực sự cần thiết sau đó - theo mặc định nó có ở đó, nhưng bạn có thể chọn không nhận mã cấp thấp. Điều tôi nghĩ là sai về điều này là tôi không thể tìm cách quay lại. Ví dụ, trong một thùng chứa dựa trên cây, mã thư viện có thể quản lý bộ nhớ cho chính các nút của cây. Toàn bộ cây vẫn có thể được thu thập, với IIRC một hàm hủy thu thập tất cả các nút đó. Nhưng các đối tượng được tham chiếu bởi dữ liệu trong thùng chứa đó cũng có thể được thu thập - cần có một móc để đánh dấu tất cả các mục dữ liệu trong cây cho GC.
Steve314

3
Bạn vẫn có thể vô hiệu hóa GC cho mã cấp thấp - Peter đang nói rằng ngôn ngữ hiện tại phụ thuộc rất nhiều vào nó. Ngoài ra, bạn có thể yêu cầu GC quét các phạm vi bên ngoài vùng heap được quản lý của mình bằng API: GC.addRange từ core.memory .
Vladimir Panteleev

+1 để chỉ ra rằng thư viện tiêu chuẩn D là rác được thu thập và mã tắt GC không phải là một interop liền mạch. Đó không phải là điều tôi nghĩ về nó, nhưng nó dường như là một trở ngại lớn cần vượt qua.
masonk

132

Khi tôi tham gia phát triển D, tôi đã ở vị trí đặc biệt là một trong những người biết nhiều nhất về C ++. Bây giờ tôi đang ở vị trí đặc biệt hơn nữa để trở thành một trong những người biết nhiều nhất về D. Tôi không nói điều này với quyền tín dụng hoặc quyền khoe khoang nhiều như nhận xét tôi đang tò mò vị trí thuận lợi để trả lời câu hỏi này. Điều tương tự cũng áp dụng cho Walter.

Nhìn chung, việc hỏi C ++ (và ý tôi là C ++ 2011) làm gì tốt hơn D là tự mâu thuẫn như câu hỏi: "Nếu bạn trả tiền cho một chuyên gia để dọn dẹp nhà cửa, những nơi họ sẽ rời đi bẩn hơn trước? " Bất kể giá trị nào là C ++ có thể làm được điều đó D không thể, nó luôn luôn đứng như ngón tay cái đau đối với tôi và Walter, vì vậy gần như theo định nghĩa, C ++ không thể làm gì trong tầm tay của D.

Một điều hiếm khi được hiểu trong thiết kế ngôn ngữ (vì ít người có may mắn thực sự làm được một số thứ) là có rất ít lỗi không được thực thi hơn so với nó có thể xuất hiện. Nhiều người dùng ngôn ngữ của chúng tôi nhìn vào một số cấu trúc này hoặc cấu trúc khác và nói, "Ew! Điều này thật sai lầm! Họ đã nghĩ gì?" Thực tế của vấn đề là hầu hết các trường hợp lúng túng trong ngôn ngữ là hậu quả của một vài quyết định cơ bản hoàn toàn đúng đắn và mong muốn nhưng về cơ bản là cạnh tranh hoặc mâu thuẫn với nhau (ví dụ như mô-đun và hiệu quả, sự căng thẳng và kiểm soát, v.v.).

Với tất cả những điều này, tôi sẽ liệt kê một vài điều mà tôi có thể nghĩ ra và với mỗi điều tôi sẽ giải thích về sự lựa chọn của D xuất phát từ mong muốn thực hiện một số điều lệ khác, cấp cao hơn.

  1. D giả sử tất cả các đối tượng có thể di chuyển bằng cách sao chép bitwise. Điều này để lại một số ít các thiết kế cho C ++, cụ thể là những thiết kế sử dụng con trỏ bên trong, tức là một lớp chứa con trỏ bên trong chính nó. . toàn bộ morass xây dựng bản sao và tính năng tham chiếu giá trị hoàn toàn.

  2. D không cho phép các loại giới tính mơ hồ (điều đó không thể quyết định chúng là loại giá trị hay loại tham chiếu). Những thiết kế như vậy bị nhất trí xa lánh trong C ++ và hầu như luôn luôn sai, nhưng một số trong số chúng là đúng về mặt kỹ thuật. Chúng tôi đã đưa ra lựa chọn này vì nó không cho phép mã không chính xác và chỉ một mã chính xác nhỏ có thể được thiết kế lại. Chúng tôi tin rằng đó là một sự đánh đổi tốt.

  3. D không tuân theo hệ thống phân cấp đa gốc. Một poster trước đây ở đây đã rất hào hứng về chủ đề cụ thể này, nhưng đây là nền tảng tốt và không có lợi thế có thể sờ thấy của hệ thống phân cấp không gốc so với hệ thống phân cấp mà tất cả đều có gốc chung.

  4. Trong D bạn không thể ném ví dụ như một int. Bạn phải ném một đối tượng kế thừa Ném được. Không có cuộc thi nào tình trạng tốt hơn ở D, nhưng, chà, đó là một điều mà C ++ có thể làm mà D không thể.

  5. Trong C ++, đơn vị đóng gói là một lớp. Trong D đó là một mô-đun (tức là tệp). Walter đã đưa ra quyết định này vì hai lý do: lập bản đồ đóng gói một cách tự nhiên vào ngữ nghĩa bảo vệ hệ thống và để tránh sự cần thiết của "người bạn". Lựa chọn này tích hợp rất tốt trong thiết kế mô đun tổng thể của D. Có thể thay đổi mọi thứ trở nên giống với C ++ hơn, nhưng điều đó sẽ buộc mọi thứ; Các lựa chọn phạm vi đóng gói của C ++ chỉ tốt cho thiết kế vật lý của C ++.

Có thể có một hoặc hai điều nhỏ hơn, nhưng về tổng thể thì đây là nó.


6
@DeadMG: Để điều đó hoạt động trong C ++, đối tượng được di chuyển sẽ cần một con trỏ quay lại đối tượng trỏ đến nó (để nó có thể cập nhật trong quá trình xây dựng bản sao). Nếu đó là trường hợp, trong D bạn có thể sử dụng hàm tạo postblit để cập nhật con trỏ. Xin đừng tranh cãi với D nếu bạn chỉ có kiến ​​thức về nó.
Peter Alexander

13
@Peter: Nó nên là một tài liệu tham khảo mặc dù thời gian tồn tại của nó hoàn toàn dựa trên phạm vi? Tôi có nên lãng phí chi phí của việc phân bổ động nó và các chi phí bộ nhớ cache và bộ nhớ cache và bộ sưu tập vì tôi muốn đặt bí danh không? Ngoài ra, tôi hy vọng rằng người sưu tầm có thể thu thập nó một cách xác định, cho ngữ nghĩa tương đương. Điều đó khá rõ ràng là không được kiểm soát.
DeadMG

3
@sbi: Sự tồn tại của một lớp học hàng đầu hoàn toàn không ảnh hưởng đến sự lựa chọn của bạn. Trong lớp kiểu mạng, luôn có đỉnh và đáy. Dưới cùng chỉ rõ ràng trong một vài ngôn ngữ . Phần trên cùng (tức là Object, v.v.) rõ ràng bằng nhiều ngôn ngữ hơn. Những loại này luôn tồn tại trong khái niệm; khi họ cũng có thể truy cập được, họ chỉ cần cung cấp thêm một vài tiện ích cho người dùng ngôn ngữ mà không gây rắc rối.
Andrei Alexandrescu

6
@quant_dev: bạn sẽ rất vui khi biết có một dự án GSoC đã có hình dạng tốt tập trung vào đại số tuyến tính hiệu suất cao bằng BLAS. Nó cũng cung cấp các triển khai "ngây thơ" của các nguyên thủy thích hợp cho các mục đích thử nghiệm và điểm chuẩn. Để trả lời câu hỏi thứ hai của bạn, Java đặt thanh khá thấp để so sánh các thư viện số. Nó sẽ luôn gặp khó khăn khi vượt qua rào cản JNI để truy cập các lib đại số hiệu năng cao và cú pháp sẽ rất tệ vì Java thiếu quá tải toán tử.
Andrei Alexandrescu

4
@PeterAlexander: DeadMG nói đúng. "Bạn không nên sử dụng con trỏ cho các loại giá trị" rõ ràng không biết gì về thực tế là con trỏ trong bất kỳ ngôn ngữ nào thường được sử dụng với các loại giá trị (bạn có thực sự mong đợi Object*được sử dụng rộng rãi như một int*?) Và D dường như hoàn toàn bỏ qua hình phạt hiệu suất, hoặc tuyên bố nó không tồn tại. Điều đó rõ ràng là sai - lỗi bộ nhớ cache khá đáng chú ý trong nhiều trường hợp, vì vậy C ++ sẽ luôn có lợi thế linh hoạt so với D.
Mehrdad

65

Tôi nghĩ rằng bạn sẽ có một khoảng thời gian rất khó để tìm thấy nhiều thứ trong D một cách khách quantệ hơn C ++. Hầu hết các vấn đề với D nơi bạn có thể nói một cách khách quan, vấn đề tồi tệ hơn là chất lượng của các vấn đề triển khai (thường là do ngôn ngữ và cách triển khai còn non trẻ và đã được khắc phục ở tốc độ chậm), hoặc chúng là các vấn đề thiếu thư viện của bên thứ 3 (sẽ đi cùng với thời gian). Bản thân ngôn ngữ nói chung tốt hơn C ++ và các trường hợp C ++, với tư cách là ngôn ngữ, nói chung tốt hơn sẽ là nơi có sự đánh đổi khi C ++ đi một chiều và D đi theo hướng khác, hoặc ai đó có lý do chủ quan về lý do tại sao họ nghĩ rằng cái này tốt hơn cái kia Nhưng số lượng lý do khách quan hoàn toàn tại sao C ++, với tư cách là một ngôn ngữ, tốt hơn có khả năng là rất ít và xa.

Trên thực tế, tôi phải thực sự phá hủy bộ não của mình để đưa ra lý do tại sao C ++, với tư cách là một ngôn ngữ, tốt hơn D. Điều thường xuất hiện trong đầu là vấn đề đánh đổi.

  1. Bởi vì const của D mang tính bắc cầu và vì ngôn ngữ là bất biến , nên nó có sự bảo đảm mạnh mẽ hơn nhiều so với C ++ const, điều đó có nghĩa là D không và không thểmutable. Nó không thể có const logic . Vì vậy, bạn có được một lợi ích khổng lồ với hệ thống const của D, nhưng trong một số trường hợp, bạn không thể sử dụng constnhư bạn có trong C ++.

  2. D chỉ có một toán tử cast, trong khi C ++ có 4 (5 nếu bạn tính toán tử cast C). Điều này làm cho việc xử lý các phôi trong D dễ dàng hơn trong trường hợp chung, nhưng có vấn đề khi bạn thực sự muốn các biến chứng / lợi ích thêm mà const_castanh em của nó cung cấp. Nhưng D thực sự đủ mạnh để bạn có thể sử dụng các mẫu để triển khai các phôi của C ++, vì vậy nếu bạn thực sự muốn chúng, bạn có thể có chúng (và thậm chí chúng có thể kết thúc trong thư viện chuẩn của D vào một lúc nào đó).

  3. D có số lượng diễn viên ngầm ít hơn nhiều so với C ++ và có nhiều khả năng tuyên bố rằng hai hàm có xung đột với nhau (buộc bạn phải cụ thể hơn về chức năng nào mà bạn muốn nói - với các phôi hoặc bằng cách đưa ra đường dẫn mô-đun đầy đủ ). Đôi khi, điều đó có thể gây phiền nhiễu, nhưng nó ngăn chặn tất cả các loại vấn đề chiếm quyền điều khiển . Bạn biết rằng bạn đang thực sự gọi chức năng mà bạn muốn nói đến.

  4. Hệ thống mô-đun của D sạch hơn nhiều so với #inc loại của C ++ (chưa kể, cách biên dịch nhanh hơn), nhưng nó không có bất kỳ loại không gian tên nào ngoài chính các mô-đun. Vì vậy, nếu bạn muốn có một không gian tên trong một mô-đun, bạn phải đi theo tuyến Java và sử dụng các hàm tĩnh trên một lớp hoặc struct. Nó hoạt động, nhưng nếu bạn thực sự muốn không gian tên, rõ ràng nó không sạch như không gian tên thực. Tuy nhiên, đối với hầu hết các tình huống, không gian tên mà các mô-đun cung cấp cho bạn rất nhiều (và khá tinh vi khi nói đến những thứ như xung đột thực sự).

  5. Giống như Java và C #, D có thừa kế duy nhất chứ không phải là đa kế thừa, nhưng không giống như Java và C #, nó mang lại cho bạn một số cách tuyệt vời để có được những tác dụng tương tự mà không cần tất cả những vấn đề mà C ++ 'đa kế thừa s có (và C ++' đa kế thừa s có thể nhận được rất lộn xộn nhiều lúc). D không chỉ có giao diện mà còn có chuỗi mixin , mixin mẫubí danh này . Vì vậy, kết quả cuối cùng mạnh hơn nhiều và không có tất cả các vấn đề mà tính kế thừa của C ++ gây ra.

  6. Tương tự như C #, D phân tách các cấu trúccác lớp . Các lớp là các kiểu tham chiếu có sự kế thừa và có nguồn gốc từ Object, trong khi các cấu trúc là các loại giá trị không có sự kế thừa. Sự tách biệt này có thể là tốt và xấu. Nó thoát khỏi vấn đề cắt lát cổ điển trong C ++ và nó giúp tách các loại thực sự có giá trị với các loại được cho là đa hình, nhưng ít nhất, sự khác biệt có thể gây khó chịu cho lập trình viên C ++. Cuối cùng, có một số lợi ích cho nó, nhưng nó buộc bạn phải đối phó với các loại của bạn hơi khác nhau.

  7. Các hàm thành viên của các lớp là đa hình theo mặc định. Bạn không thể khai báo chúng không ảo . Tùy thuộc vào trình biên dịch để quyết định xem chúng có thể hay không (điều này thực sự chỉ xảy ra nếu chúng là cuối cùng và không ghi đè một hàm từ một lớp cơ sở). Vì vậy, đó có thể là một vấn đề hiệu suất trong một số trường hợp. Tuy nhiên, nếu bạn thực sự không cần đa hình, thì tất cả những gì bạn phải làm là sử dụng các cấu trúc , và đó không phải là vấn đề.

  8. D có bộ thu gom rác tích hợp . Nhiều người từ C ++ sẽ coi đó là một nhược điểm nghiêm trọng, và sự thật được nói, hiện tại, việc thực hiện nó có thể sử dụng một số công việc nghiêm túc. Nó đã được cải thiện, nhưng nó chắc chắn không ngang tầm với trình thu gom rác của Java. Tuy nhiên, điều này được giảm nhẹ bởi hai yếu tố. Thứ nhất, nếu bạn chủ yếu sử dụng cấu trúc và các loại dữ liệu khác trên ngăn xếp, thì đó không phải là vấn đề lớn. Nếu chương trình của bạn không liên tục phân bổ và phân bổ công cụ trên heap, nó sẽ ổn thôi. Và hai, bạn có thể bỏ qua trình thu gom rác nếu bạn muốn và chỉ sử dụng C mallocfree. Có một số tính năng ngôn ngữ (chẳng hạn như cắt mảng) mà bạn sẽ phải tránh hoặc cẩn thận và một số thư viện tiêu chuẩn không thực sự có thể sử dụng được mà ít nhất là sử dụng GC (đặc biệt là xử lý chuỗi), nhưng bạn có thể viết vào D mà không cần sử dụng trình thu gom rác nếu bạn thực sự muốn Điều thông minh cần làm có lẽ là thường sử dụng nó và sau đó tránh nó ở nơi hồ sơ cho thấy rằng nó gây ra vấn đề cho mã quan trọng về hiệu năng, nhưng bạn có thể tránh hoàn toàn nếu bạn muốn. Và chất lượng thực hiện của GC sẽ cải thiện theo thời gian, loại bỏ nhiều mối lo ngại rằng việc sử dụng một GC có thể gây ra. Vì vậy, cuối cùng, GC sẽ không phải là vấn đề lớn và không giống như Java, bạn có thể tránh nó nếu muốn.

Có lẽ cũng có những người khác, nhưng đó là những gì tôi có thể nghĩ ra vào lúc này. Và nếu bạn chú ý, tất cả đều là sự đánh đổi. D đã chọn làm một số điều khác với C ++ có những lợi thế nhất định so với cách C ++ thực hiện chúng nhưng cũng có một số nhược điểm. Cái nào tốt hơn phụ thuộc vào những gì bạn đang làm, và trong nhiều trường hợp có thể sẽ chỉ có vẻ tồi tệ hơn lúc đầu và sau đó bạn sẽ không gặp vấn đề gì với nó một khi bạn đã quen với nó. Nếu bất cứ điều gì, các vấn đề trong D nói chung sẽ là những vấn đề mới gây ra bởi những thứ mới mà các ngôn ngữ khác chưa từng làm trước đây hoặc chưa được thực hiện theo cách mà D có. Nhìn chung, D đã học rất tốt từ những sai lầm của C ++.

Và D, như một ngôn ngữ, cải thiện C ++ theo nhiều cách mà tôi nghĩ rằng nói chung là trường hợp D tốt hơn về mặt khách quan.

  1. D có biên dịchđiều kiện . Đây là một trong những tính năng mà tôi thường xuyên bỏ lỡ khi tôi lập trình trong C ++. Nếu C ++ sẽ thêm nó, thì C ++ sẽ cải thiện bằng những bước nhảy vọt khi nói đến những thứ như các mẫu.

  2. D có phản xạ thời gian biên dịch .

  3. Các biến được mặc định là luồng cục bộ nhưng có thể là sharednếu bạn muốn chúng là. Điều này làm cho đối phó với chủ đề xa sạch hơn trong C ++. Bạn hoàn toàn kiểm soát. Bạn có thể sử dụng immutablechuyển thông điệp để giao tiếp giữa các luồng hoặc bạn có thể tạo các biến sharedvà thực hiện theo cách C ++ với các biến và biến điều kiện. Thậm chí điều đó còn được cải thiện so với C ++ với việc giới thiệu đồng bộ hóa (tương tự C # và Java). Vì vậy, D's tình hình luồng là xa tốt hơn so với C ++ 's.

  4. Các mẫu của D mạnh hơn rất nhiều so với các mẫu của C ++, cho phép bạn làm được nhiều hơn, dễ dàng hơn nhiều. Và với việc bổ sung các mẫu hạn chế, các thông báo lỗi là cách tốt hơn so với họ đang có trong C ++. D làm cho các mẫu rất mạnh mẽ và có thể sử dụng. Không phải ngẫu nhiên mà tác giả của Modern C ++ Design là một trong những cộng tác viên chính của D. Tôi thấy các mẫu C ++ thiếu nghiêm trọng so với các mẫu D và đôi khi nó có thể rất bực bội khi lập trình trong C ++.

  5. D đã tích hợp sẵn chương trình hợp đồng .

  6. D có khung kiểm tra đơn vị tích hợp .

  7. D có hỗ trợ tích hợp cho unicode với string(UTF-8), wstring(UTF-16) và dstring(UTF-32). Nó làm cho nó dễ dàng để đối phó với unicode. Và nếu bạn chỉ muốn sử dụng stringvà thường không lo lắng về unicode, bạn có thể - mặc dù một số hiểu biết cơ bản về unicode có ích với một số chức năng thư viện tiêu chuẩn.

  8. Quá tải toán tử của D đẹp hơn nhiều so với C ++, cho phép bạn sử dụng một hàm để quá tải nhiều toán tử cùng một lúc. Một ví dụ điển hình của điều này là khi bạn cần quá tải các toán tử số học cơ bản và việc triển khai chúng là lưu giống hệt nhau cho toán tử. Chuỗi mixins làm cho nó dễ dàng, cho phép bạn có một định nghĩa hàm đơn giản cho tất cả chúng.

  9. Mảng của D tốt hơn rất nhiều so với mảng của C ++. Chúng không chỉ là một loại thích hợp với chiều dài, mà chúng còn có thể được thêm vào và thay đổi kích thước. Nối chúng là dễ dàng. Và tốt nhất của tất cả, họ đã cắt . Và đó là một lợi ích lớn cho việc xử lý mảng hiệu quả. Chuỗi là mảng các ký tự trong D và nó không phải là vấn đề (thực tế nó rất tuyệt!), Bởi vì mảng của D rất mạnh.

Tôi có thể đi và về. Rất nhiều cải tiến mà D cung cấp là những điều nhỏ nhặt (như sử dụng thischo tên của nhà xây dựng hoặc không cho phép nếu các câu lệnh hoặc các vòng lặp trong đó dấu chấm phẩy là toàn bộ cơ thể của chúng), nhưng một số trong số chúng khá lớn và khi bạn kết hợp tất cả lại với nhau, thì nó làm cho trải nghiệm lập trình tốt hơn nhiều . C ++ 0x có thêm một số tính năng mà D có thiếu C ++ (ví dụ autovà lambdas), nhưng ngay cả với tất cả các cải tiến của nó, vẫn sẽ không có nhiều ngôn ngữ tốt hơn về ngôn ngữ của C ++ so với D.

Không có câu hỏi rằng có rất nhiều lý do chủ quan để thích cái này và sự non nớt tương đối của việc triển khai D có thể là một vấn đề đôi khi (mặc dù nó đã được cải thiện rất nhanh về muộn - đặc biệt là khi các kho lưu trữ đã được chuyển sang github ) và việc thiếu thư viện của bên thứ 3 chắc chắn có thể là một vấn đề (mặc dù thực tế là D có thể dễ dàng gọi các hàm C - và ở mức độ thấp hơn, các hàm C ++ - chắc chắn giảm nhẹ vấn đề). Nhưng đó là chất lượng của các vấn đề thực hiện hơn là các vấn đề với chính ngôn ngữ. Và khi chất lượng của các vấn đề triển khai được cố định, việc sử dụng D. sẽ trở nên dễ chịu hơn nhiều.

Vì vậy, tôi cho rằng câu trả lời ngắn cho câu hỏi này là "rất ít". D, như một ngôn ngữ, nói chung là vượt trội so với C ++.


2
Các ngôn ngữ thu gom rác sử dụng bộ nhớ nhiều hơn gấp 2 lần so với các ngôn ngữ không phải là GC (theo bài nói của Alexandrescu trên YT), vì vậy đó chắc chắn là một vấn đề nếu điều đó (việc sử dụng mem) là nút cổ chai.
NoSenseEtAl

9

RAII và ngăn xếp sử dụng bộ nhớ

D 2.0 không cho phép RAII xảy ra trên ngăn xếp vì nó đã loại bỏ giá trị của scopetừ khóa trong việc phân bổ các thể hiện của lớp trên ngăn xếp.

Bạn không thể thực hiện kế thừa loại giá trị trong D, do đó buộc bạn phải thực hiện phân bổ heap cho bất kỳ hình thức RAII nào.
Đó là, trừ khi bạn sử dụng emplace, nhưng điều đó rất đau khi sử dụng, vì bạn phải phân bổ bộ nhớ bằng tay. (Tôi vẫn chưa thấy nó thực tế khi sử dụng emplacetrong D.)


6

C ++ tốt hơn nhiều khi buộc bạn phải dài dòng. Điều này có thể tốt hơn hoặc tồi tệ hơn trong mắt bạn, tùy thuộc vào việc bạn thích suy luận hay dài dòng.

So sánh ghi nhớ thời gian chạy trong C ++ :

template <typename ReturnType, typename... Args>
function<ReturnType (Args...)> memoize(function<ReturnType (Args...)> func)
{
    map<tuple<Args...>, ReturnType> cache;
    return ([=](Args... args) mutable {
            tuple<Args...> t(args...);
            return cache.find(t) == cache.end()
                ? cache[t] : cache[t] = func(args...);
    });
}

với điều tương tự trong D:

auto memoize(F)(F func)
{
    alias ParameterTypeTuple!F Args;
    ReturnType!F[Tuple!Args] cache;
    return (Args args)
    {
        auto key = tuple(args);
        return key in cache ? cache[key] : (cache[key] = func(args));
    };
}

Lưu ý, ví dụ, mức độ dài thêm với template <typename ReturnType, typename... Args>so với (F), Args...so với Args, args...so với args, v.v ...
Để tốt hơn hoặc tồi tệ hơn, C ++ dài dòng hơn.

Tất nhiên, bạn cũng có thể làm điều này trong D:

template memoize(Return, Args...)
{
    Return delegate(Args) memoize(Return delegate(Args) func)
    {
        Return[Tuple!Args] cache;
        return delegate(Args args)
        {
            auto key = tuple(args);
            return key in cache ? cache[key] : (cache[key] = func(args));
        };
    }
}

và chúng trông gần giống nhau, nhưng sau đó điều này sẽ yêu cầu một delegate, trong khi bản gốc chấp nhận bất kỳ đối tượng có thể gọi được. (Phiên bản C ++ 0x yêu cầu mộtstd::function đối tượng.


2

Tôi không biết nhiều về D, nhưng nhiều, rất nhiều lập trình viên C ++ mà tôi biết rất không thích nó và cá nhân tôi phải đồng ý - Tôi không thích giao diện của D và sẽ không xem xét kỹ hơn.

Để hiểu lý do tại sao D không tăng thêm lực kéo, bạn cần bắt đầu bằng cách hiểu điều gì thu hút mọi người đến với C ++. Trong một từ, lý do số một là kiểm soát. Khi bạn lập trình trong C ++, thì bạn có toàn quyền kiểm soát chương trình của mình. Bạn muốn thay thế thư viện tiêu chuẩn? Bạn có thể. Bạn muốn làm phôi con trỏ không an toàn? Bạn có thể. Bạn muốn vi phạm const-đúng? Bạn có thể. Bạn muốn thay thế bộ cấp phát bộ nhớ? Bạn có thể. Bạn muốn sao chép xung quanh bộ nhớ thô mà không quan tâm đến loại của nó? Nếu bạn thực sự muốn. Bạn muốn kế thừa từ nhiều triển khai? Đây là đám tang của bạn. Địa ngục, bạn thậm chí có thể có được các thư viện thu gom rác, như bộ sưu tập Boehm. Sau đó, bạn có các vấn đề như hiệu suất, theo sát kiểm soát - lập trình viên càng kiểm soát nhiều, anh ta càng có thể tối ưu hóa chương trình của mình.

Đây là một vài điều mà tôi đã thấy khi thực hiện một nghiên cứu nhỏ và nói chuyện với một vài người đã thử nó:

Phân cấp kiểu thống nhất. Người dùng C ++ rất hiếm khi sử dụng tính kế thừa, hầu hết các lập trình viên C ++ thích thành phần và các loại chỉ nên được liên kết thông qua kế thừa nếu có lý do rất chính đáng để làm như vậy. Khái niệm về Object vi phạm nguyên tắc này mạnh mẽ bằng cách liên kết mọi loại. Ngoài ra, nó vi phạm một trong những nguyên tắc cơ bản nhất của C ++ - bạn chỉ sử dụng những gì bạn muốn. Không được đưa ra lựa chọn về việc kế thừa từ Object và các chi phí đi kèm với nó, rất mạnh so với những gì C ++ đại diện cho ngôn ngữ trong việc giúp lập trình viên kiểm soát chương trình của mình.

Tôi đã nghe về các vấn đề với chức năng và đại biểu. Rõ ràng, D có cả hai chức năng đại biểu là các loại chức năng có thể gọi được trong thời gian chạy và chúng không giống nhau nhưng chúng có thể hoán đổi cho nhau hoặc ... một cái gì đó? Bạn tôi đã có một vài vấn đề với họ. Đây chắc chắn là một sự hạ cấp từ C ++, vừa mới std::functionhoàn thành.

Sau đó, bạn đã có khả năng tương thích. D không tương thích đặc biệt với C ++. Ý tôi là, không có ngôn ngữ nào tương thích với C ++, hãy đối mặt với nó, ngoại trừ C ++ / CLI là một loại gian lận, nhưng như một rào cản gia nhập, nó phải được đề cập.

Sau đó, có một số điều khác. Ví dụ, chỉ cần đọc mục Wikipedia.

import std.metastrings;
pragma(msg, Format!("7! = %s", fact_7));
pragma(msg, Format!("9! = %s", fact_9));

printflà một trong những chức năng không an toàn nhất từng được phát minh, trong cùng một gia đình với các vấn đề lớn như getstừ thư viện C Standard cũ. Nếu bạn tìm kiếm nó trên Stack Overflow, bạn sẽ tìm thấy rất nhiều câu hỏi liên quan đến việc sử dụng sai. Về cơ bản, printflà vi phạm DRY- bạn đang đưa ra loại trong chuỗi định dạng và sau đó cung cấp lại khi bạn đưa ra một đối số. Vi phạm DRY nếu bạn hiểu sai, thì điều rất tệ sẽ xảy ra - giả sử, nếu bạn thay đổi một typedef từ số nguyên 16 bit thành số 32 bit. Nó cũng không thể mở rộng được - hãy tưởng tượng điều gì sẽ xảy ra nếu mọi người phát minh ra các công cụ định dạng riêng của họ. Các iostream của C ++ có thể chậm và sự lựa chọn nhà điều hành của họ có thể không phải là tốt nhất và giao diện của họ có thể sử dụng công việc, nhưng về cơ bản chúng được đảm bảo an toàn và DRY không bị vi phạm và chúng có thể được mở rộng. Đây không phải là điều có thể nói printf.

Không thừa kế nhiều. Đó không phải là cách của C ++. Các lập trình viên C ++ mong muốn có toàn quyền kiểm soát chương trình của họ và ngôn ngữ thực thi những gì bạn không thể thừa hưởng là vi phạm nguyên tắc đó. Ngoài ra, nó làm cho tính kế thừa (thậm chí nhiều hơn) trở nên dễ vỡ, bởi vì nếu bạn thay đổi một loại từ giao diện sang một lớp vì bạn muốn cung cấp một triển khai mặc định hoặc một cái gì đó, đột nhiên tất cả mã người dùng của bạn bị hỏng. Đó không phải là một điều tốt.

Một ví dụ khác là stringwstring. Trong C ++, thật khó khăn khi phải chuyển đổi giữa chúng và thư viện này có hỗ trợ Unicode không, và thư viện C cũ này chỉ sử dụng const char*và phải viết các phiên bản khác nhau của cùng một chức năng tùy thuộc vào loại đối số chuỗi bạn muốn. Đáng chú ý, các tiêu đề Windows, ví dụ, có một số macro cực kỳ khó chịu để đối phó với vấn đề thường có thể can thiệp vào mã của riêng bạn. Thêm dstringvào hỗn hợp sẽ chỉ làm cho mọi thứ tồi tệ hơn, vì bây giờ thay vì hai loại chuỗi, bạn phải quản lý ba. Có nhiều hơn một loại chuỗi sẽ làm tăng các cơn đau bảo trì và giới thiệu mã lặp đi lặp lại xử lý các chuỗi.

Scott Meyers viết:

D là một ngôn ngữ lập trình được xây dựng để giúp các lập trình viên giải quyết các thách thức của phát triển phần mềm hiện đại. Nó làm như vậy bằng cách thúc đẩy các mô-đun được kết nối với nhau thông qua các giao diện chính xác, liên kết các mô hình lập trình tích hợp chặt chẽ, cách ly luồng thực thi ngôn ngữ, an toàn kiểu mô-đun, mô hình bộ nhớ hiệu quả, v.v.

Cách ly luồng thực thi ngôn ngữ không phải là một cộng. Các lập trình viên C ++ mong đợi toàn quyền kiểm soát các chương trình của họ và ngôn ngữ buộc một thứ gì đó chắc chắn không phải là thứ mà bác sĩ đã yêu cầu.

Tôi cũng sẽ đề cập đến thao tác chuỗi thời gian biên dịch. D có khả năng diễn giải mã D tại thời gian biên dịch. Đây không phải là một điểm cộng. Hãy xem xét những cơn đau đầu dữ dội do bộ tiền xử lý tương đối hạn chế của C, được biết đến bởi tất cả các lập trình viên C ++ kỳ cựu, và sau đó tưởng tượng tính năng này sẽ bị lạm dụng đến mức nào. Khả năng tạo mã D tại thời gian biên dịch là rất tốt, nhưng nó phải là ngữ nghĩa , không phải cú pháp.

Ngoài ra, bạn có thể mong đợi một phản xạ nhất định. D có bộ sưu tập rác, mà các lập trình viên C ++ sẽ liên kết với các ngôn ngữ như Java và C # hoàn toàn trái ngược với nó trong các triết lý và sự tương đồng về cú pháp cũng sẽ khiến họ chú ý. Điều này không nhất thiết phải khách quan chính đáng, nhưng đó là điều chắc chắn cần lưu ý.

Về cơ bản, nó không cung cấp nhiều mà các lập trình viên C ++ không thể làm được. Có thể dễ dàng hơn để viết một siêu dữ liệu giai thừa trong D, nhưng chúng ta đã có thể viết các siêu dữ liệu giai thừa trong C ++. Có thể trong D bạn có thể viết một trình theo dõi thời gian biên dịch, nhưng dù sao thì không ai thực sự muốn làm điều đó. So với các vi phạm cơ bản của triết lý C ++, những gì bạn có thể làm trong D không đặc biệt đáng chú ý.

Ngay cả khi những điều này chỉ là vấn đề trên bề mặt, thì tôi khá chắc chắn rằng thực tế là trên bề mặt, D hoàn toàn không giống C ++ có lẽ là một lý do chính đáng mà nhiều lập trình viên C ++ không chuyển sang D. Có lẽ D cần phải tự làm một công việc quảng cáo tốt hơn.


9
@DeadMG: Điều đó không chính xác 100% và thiếu điểm để nói Đây chắc chắn là một sự hạ cấp từ C ++, điều vừa có std::functionvà bạn đã hoàn thành. Tại sao? Bởi vì bạn cũng, ví dụ, có con trỏ hàm. Đó chính xác là điều tương tự trong "chức năng" của D: D là các con trỏ hàm và "đại biểu" của D giống như của C ++ std::function(ngoại trừ việc chúng được tích hợp sẵn). Không có "hạ cấp" bất cứ nơi nào - và có sự tương ứng 1: 1 giữa chúng, do đó, không nên nhầm lẫn nếu bạn quen thuộc với C ++.
Mehrdad

10
@Mark Trapp: Tôi phải thừa nhận rằng tôi không hiểu rõ lập trường của bạn về chủ đề này - bạn không biết bình luận nào , bình luận về câu trả lời?
klickverbot

6
@Mark Trapp: Quan điểm của tôi là hầu hết các bình luận ở đây không bị lỗi thời (cuộc thảo luận meta mà bạn liên kết áp dụng cụ thể cho các đề xuất đã được đưa vào bài viết gốc), nhưng chỉ ra sự thiếu chính xác trong bài viết, vẫn còn hiện diện .
klickverbot

7
Lưu ý về định dạng: Hàm định dạng của D là loại an toàn (giải quyết các vấn đề an toàn / tràn) và không vi phạm DRY vì chuỗi định dạng chỉ xác định cách các đối số nên được định dạng, không phải loại của chúng. Điều này có thể là nhờ các loại dao động an toàn của D. Do đó, sự phản đối đó ít nhất là hoàn toàn không hợp lệ.
Justin W

17
@Mark: Bất kể chính sách hiện tại liên quan đến họ là gì, tôi thấy thật ngu ngốc và cản trở việc thảo luận bình luận bị xóa . Tôi nghĩ rằng câu trả lời này đã có các cuộc thảo luận rộng rãi (mà bây giờ tôi quan tâm), nhưng tôi không chắc chắn, và tôi không có cách nào để tìm hiểu. Căn phòng mà bạn liên kết có hơn 10 nghìn tin nhắn và tôi hoàn toàn không có cơ hội tìm thấy một cuộc thảo luận mà tôi dường như nhớ đã diễn ra, nhưng không thể nhớ nội dung của nó. Các cuộc thảo luận liên quan đến câu trả lời này thuộc về câu trả lời này , chứ không phải cho một số phòng trò chuyện, nơi họ có thể bị lẫn lộn trong các cuộc thảo luận về tình dục, ma túy và rock'n'roll.
sbi

1

Một điều tôi đánh giá cao trong C ++ là khả năng ghi lại một đối số hàm hoặc trả về giá trị dưới dạng tham chiếu C ++ thay vì con trỏ, do đó ngụ ý lấy một nullgiá trị không .

Phiên bản D:

class A { int i; }

int foo(A a) {
    return a.i; // Will crash if a is null
}

int main() {
    A bar = null;
    // Do something, forgetting to set bar in all
    // branches until finally ending up at:
    return foo(bar);
}

Phiên bản C ++:

class A { int i; };

int foo(A& a) {
    return a.i; // Will probably not crash since
                // C++ references are less likely
                // to be null.
}

int main() {
    A* bar = null;
    // Do something, forgetting to set bar in all
    // branches until finally ending up at:
    // Hm.. I have to dereference the bar-pointer
    // here, otherwise it wont compile.  Lets add
    // a check for null before.
    if (bar)
        return foo(*bar);
    return 0;
}

Để công bằng, bạn có thể đến rất gần với C ++ bằng cách tạo Athành một D structvà đánh dấu foo()-argument là một ref(các lớp là các kiểu tham chiếu và các cấu trúc là các loại giá trị trong D, tương tự như C #).

Tôi tin rằng có một kế hoạch để tạo một NonNullablemẫu cho các lớp như là một thư viện chuẩn D xây dựng thay thế. Mặc dù vậy, tôi thích sự ngắn gọn của việc Type&so sánh với NonNullable(Type), và sẽ thích không có giá trị như mặc định (hiển thị một cái gì đó giống như TypeNullable(Type)). Nhưng đã quá muộn để thay đổi điều đó cho D và tôi đang lạc đề.


3
Cả hai đối số hàm và giá trị trả về trong D đều có thể được đánh dấu refđể mang lại cho bạn hiệu ứng giống như của C ++ &. Sự khác biệt chính là refsẽ không tạm thời ngay cả khi nó const.
Jonathan M Davis

Tôi thích cách trả về các tham chiếu đến các biến cục bộ bị cấm trong D, tôi không biết điều đó cho đến khi tôi đọc bình luận của bạn. Nhưng bạn vẫn có thể trả về một tham chiếu null không cục bộ mà không cần suy nghĩ về nó theo cách mà toán tử điều chỉnh C sẽ khiến bạn phải suy nghĩ.
lumor

Bạn đang bối rối những điều. Các lớp học luôn là tài liệu tham khảo và tách biệt với ref. Tài liệu tham khảo trong D giống như tài liệu tham khảo trong Java. Họ được quản lý con trỏ. Vượt qua hoặc trở lại bằng ref cũng giống như vượt qua hoặc quay lại với & trong C ++. Truyền tham chiếu lớp bằng ref cũng giống như chuyển một con trỏ trong C ++ với & (ví dụ A * &). Các lớp học không đi vào ngăn xếp. Có, NonNullable sẽ có thể có một tham chiếu lớp được đảm bảo là không rỗng, nhưng nó hoàn toàn tách biệt với ref. Những gì bạn đang cố gắng làm trong mã C ++ không hoạt động trong D vì các lớp không đi vào ngăn xếp. Cấu trúc làm.
Jonathan M Davis

1
Vì vậy, có, có thể có một tham chiếu lớp không phải là nullabe, nhưng C ++ quản lý để thực hiện những gì bạn đang hiển thị vì nó cho phép các lớp nằm trên ngăn xếp và cho phép các con trỏ được hủy đăng ký. Và trong khi bạn có thể tham chiếu con trỏ trong D, các lớp là tài liệu tham khảo, không phải con trỏ, vì vậy bạn không thể hủy đăng ký chúng. Vì bạn không thể đặt chúng vào ngăn xếp và bạn không thể hủy bỏ chúng, nên không có cách nào được tích hợp vào D để có một lớp không thể rỗng. Đó một mất mát, nhưng NonNullable sẽ khắc phục nó, và lợi ích từ việc phân tách các cấu trúc và các lớp thường lớn hơn.
Jonathan M Davis

2
Các tham chiếu C ++ không thể là null theo tiêu chuẩn ngôn ngữ (nói "có lẽ sẽ không null" là không chính xác vì nó không thể là null). Tôi ước có một cách để không cho phép null là một giá trị hợp lệ cho một lớp.
jsternberg

1

Điều quan trọng nhất mà C ++ "làm tốt hơn" so với D là giao tiếp với các thư viện cũ . Động cơ 3D khác nhau, OpenCL và như nhau. Vì D là mới, nó có số lượng thư viện khác nhau nhỏ hơn nhiều để lựa chọn.

Một điểm khác biệt quan trọng giữa C ++ và D là C ++ có nhiều nhà cung cấp độc lập về tài chính, nhưng đến năm 2014, D thực tế chỉ có một , nhóm 2 người tạo ra nó. Thật thú vị khi "nguyên tắc nguồn thứ hai" nói rằng các dự án không bao giờ nên phụ thuộc vào công nghệ, các thành phần, chỉ có một, một nhà cung cấp, dường như giữ được ngay cả đối với phần mềm.

Để so sánh, phiên bản đầu tiên của trình thông dịch Ruby được viết bởi nhà phát minh của Ruby, Yukihiro Matsumoto, nhưng phiên dịch viên chính của Ruby thời kỳ 2014 đã được người khác viết thực tế từ đầu. Do đó, Ruby có thể được coi là một ngôn ngữ có nhiều hơn một nhà cung cấp độc lập về tài chính. D, mặt khác, có thể là một công nghệ tuyệt vời, nhưng nó phụ thuộc vào một vài nhà phát triển phát triển nó.

Lịch sử của Java cho thấy ngay cả khi một công nghệ, trong trường hợp này, Java, có tài chính tốt, nhưng độc thân, có một rủi ro lớn là về cơ bản công nghệ đó bị bỏ rơi, bất kể cơ sở người dùng doanh nghiệp khổng lồ. Một trích dẫn của Quỹ phần mềm Apache , nơi EC là viết tắt của "Ủy ban điều hành":

Oracle đã cung cấp cho EC một yêu cầu và giấy phép đặc tả Java SE 7 tự mâu thuẫn, hạn chế nghiêm ngặt việc phân phối các triển khai độc lập của thông số kỹ thuật và quan trọng nhất là cấm phân phối các triển khai nguồn mở độc lập của thông số kỹ thuật.

Như một ghi chú lịch sử, có thể nói rằng các applet Java đã tăng tốc phần cứng 3D nhiều năm trước khi HTML5 WebGL được phát triển. Vấn đề tốc độ khởi động của các applet Java có thể đã được giải quyết, nếu Java là một dự án cộng đồng, nhưng các giám đốc điều hành của nhà tài chính duy nhất của Java, Sun microsystems, đã không thấy nó đủ quan trọng để sửa lỗi triển khai Java. Kết quả cuối cùng: khung vẽ HTML5 của nhiều nhà cung cấp dưới dạng "bản sao của người nghèo" của các khung công tác Java GUI (Xoay, v.v.). Thật thú vị, về phía máy chủ, ngôn ngữ lập trình Python có những ưu điểm giống như Java đã hứa: viết một lần, chạy trên mọi máy chủ, bất kể phần cứng, miễn là ứng dụng Python không được biên dịch thành mã máy. Python cũng già / trẻ như Java, nhưng không giống như Java, nó '

Tóm lược:

Khi đánh giá công nghệ để sử dụng sản xuất, các thuộc tính quan trọng nhất của công nghệ là con người, người phát triển nó, quá trình xã hội, nơi phát triển diễn ra và số lượng nhóm phát triển độc lập về tài chính.

Việc sử dụng công nghệ T1 hơn công nghệ T2 có thuận lợi hơn hay không phụ thuộc vào các nhà cung cấp công nghệ và liệu công nghệ T1 có cho phép giải quyết các vấn đề liên quan đến dự án với giá rẻ hơn so với T2 hay không. Ví dụ: nếu vấn đề nhà cung cấp đơn lẻ bị bỏ qua, thì đối với các hệ thống thông tin, Java sẽ là công nghệ "tốt hơn" so với C ++, vì các nhị phân Java không cần biên dịch lại khi triển khai phần cứng mới và công việc phát triển phần mềm liên quan đến quản lý bộ nhớ nhỏ hơn đối với Java so với C ++. Các dự án được phát triển từ đầu, ví dụ như các dự án không phụ thuộc vào các thư viện khác, có thể rẻ hơn để phát triển trong D so với C ++, nhưng mặt khác, C ++ có nhiều hơn một nhà cung cấp và do đó ít rủi ro hơn về lâu dài . (Ví dụ về Java, nơi Sun microsystems gần như ổn,

Cách giải quyết có thể có đối với một số Hạn chế của C ++

Một trong những cách giải quyết có thể có đối với một số hạn chế của C ++ là sử dụng một mẫu thiết kế, trong đó nhiệm vụ ban đầu được thực hiện thành từng mảnh và các mảnh được "sắp xếp" (phân loại, phân cụm, chia, các từ đẹp khác cho- cùng một thứ) với 2 lớp: điều khiển các tác vụ liên quan đến logic , trong đó các mẫu truy cập bộ nhớ không cho phép cục bộ; nhiệm vụ giống như xử lý tín hiệu , nơi địa phương dễ dàng đạt được. Các tác vụ "thích" xử lý tín hiệu có thể được thực hiện như một tập hợp các chương trình điều khiển tương đối đơn giản. Các tác vụ liên quan đến logic điều khiển được đặt tất cả vào một tập lệnh được viết bằng Ruby hoặc Python hoặc một cái gì đó, trong đó sự thoải mái phát triển phần mềm có mức độ ưu tiên cao hơn tốc độ.

Để tránh khởi tạo quy trình hệ điều hành đắt tiền và sao chép dữ liệu giữa các quy trình của hệ điều hành, bộ ứng dụng bảng điều khiển C ++ nhỏ có thể được triển khai dưới dạng một chương trình C ++ duy nhất được khởi động dưới dạng "servlet" bởi Ruby / Python / etc. kịch bản. Ruby / Python / v.v. kịch bản tắt servlet xuống trước khi thoát. Giao tiếp giữa "servlet" và Ruby / Python / vv. kịch bản diễn ra trên một ống có tên Linux hoặc một số cơ chế tương tự.

Nếu tác vụ ban đầu không cho phép dễ dàng phân chia thành các phần có thể được phân loại thành 2 lớp đã nói ở trên, thì một điều cần thử có thể là diễn đạt lại vấn đề để nhiệm vụ ban đầu thay đổi.

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.