Ồ vâng, nó được sử dụng. Tôi làm việc trong lĩnh vực xử lý gói mạng. Tôi đã ở hai công ty khác nhau nơi chúng tôi xử lý các gói mạng. Vì vậy, chúng tôi đang hoạt động ở cấp độ Ethernet hoặc IP, không phải ở cấp độ trên TCP.
Thật thú vị, trong cả hai công ty C đã được chọn hơn C ++. Tại một trong các công ty, một trong hai sản phẩm được xây dựng dựa trên nhân Linux, trong khi sản phẩm kia được xây dựng trong không gian người dùng Linux. Sản phẩm kernel rõ ràng được sử dụng C làm kernel Linux được lập trình bằng C, nhưng họ cũng chọn sử dụng C cho sản phẩm không gian người dùng. Cả hai sản phẩm được phát triển bắt đầu từ khoảng năm 2000 (sản phẩm kernel một chút trước năm 2000 và sản phẩm không gian người dùng một chút sau năm 2000).
Trong công ty nơi tôi đã đến sau đó, sản phẩm được xây dựng trên C, không phải trên C ++. Nó thực sự là sự tiếp nối của một dự án từ giữa những năm 1990, mặc dù do nhu cầu cải thiện hiệu suất gần đây, người ta đã quyết định rằng về cơ bản mọi thứ sẽ được viết lại. Chúng tôi có một tùy chọn để chọn C ++ do viết lại này, nhưng không làm như vậy.
Trong lĩnh vực xử lý gói mạng, hiệu năng được tính rất nhiều. Vì vậy, tôi muốn triển khai bảng băm của riêng mình có hiệu suất cao hơn các bảng băm hiện có. Tôi, không phải là tác giả bảng băm, là người chọn chức năng băm nào sẽ được sử dụng. Có lẽ tôi muốn hiệu suất và đi cho MurMurHash3 . Có lẽ tôi muốn bảo mật và đi cho SipHash . Cấp phát bộ nhớ rõ ràng là tùy chỉnh. Trong thực tế, tất cả các cấu trúc dữ liệu quan trọng chúng tôi sử dụng đã được triển khai tùy chỉnh để có hiệu suất cao nhất có thể.
Mặc dù không có gì có thể ngăn cản việc sử dụng C ++, nhưng đó thường là một ý tưởng tồi. Một ngoại lệ được ném cho mỗi gói sẽ giảm tốc độ xử lý gói xuống mức không thể chấp nhận được! Vì vậy, chúng tôi không thể sử dụng ngoại lệ của C ++. Cách quá chậm. Chúng tôi đã sử dụng loại mã C hướng đối tượng bằng cách triển khai các cấu trúc dữ liệu dưới dạng các cấu trúc và sau đó thực hiện các chức năng hoạt động trên các cấu trúc đó. C ++ sẽ cho phép có các chức năng ảo, nhưng sau đó các cuộc gọi chức năng ảo sẽ giết hiệu năng nếu được sử dụng ở mọi nơi. Vì vậy, tốt hơn là nên rõ ràng và có một con trỏ hàm nếu cần các lệnh gọi ảo.
C ++ sẽ làm rất nhiều thứ sau lưng bạn: cấp phát bộ nhớ, v.v. Mặt khác, trong C thường không xảy ra. Bạn có thể viết một hàm phân bổ bộ nhớ, nhưng thông thường thì rõ ràng từ giao diện của chức năng phân bổ đang diễn ra.
Ví dụ về loại tối ưu hóa vi mô mà bạn có thể thực hiện khi lập trình trong C, hãy xem macro container_of trong nhân Linux. Chắc chắn, bạn có thể sử dụng container_of trong mã C ++, nhưng ai làm điều đó? Ý tôi là, nó hoàn toàn có thể chấp nhận được trong hầu hết các chương trình C, nhưng các lập trình viên C ++ điển hình sẽ ngay lập tức đề xuất một cái gì đó khác, chẳng hạn như một danh sách được liên kết phân bổ các nút liên kết thành các khối riêng biệt. Chúng tôi không muốn điều đó bởi vì mọi khối bộ nhớ được phân bổ đều không tốt cho hiệu năng.
Có lẽ điều duy nhất có lợi cho chúng ta trong C ++ là C ++ cho phép lập trình siêu mẫu, nghĩa là đôi khi bạn có thể tránh các cuộc gọi hàm ảo trong khi vẫn có tham số hàm và cho phép trình biên dịch nội tuyến các hàm. Nhưng siêu lập trình mẫu rất phức tạp và chúng tôi đã quản lý để đáp ứng tất cả các yêu cầu trong C, vì vậy lợi ích của tính năng này trong C ++ không quá quan trọng.
Trong một trong các công ty, chúng tôi thực sự có một ngôn ngữ được biên dịch tùy chỉnh trong đó một phần của các tính năng được triển khai. Đoán xem đó là ngôn ngữ đích của trình biên dịch? Hội,, tổ hợp? Không, chúng tôi phải hỗ trợ cả kiến trúc 32 bit và 64 bit. C ++? Chắc chắn bạn vui vẻ. Rõ ràng, đó là C với goto được tính toán của GCC . Vì vậy, ngôn ngữ tùy chỉnh đã được biên dịch thành C (hoặc thực tế là biến thể gcc của C hỗ trợ goto tính toán) và trình biên dịch C được sản xuất lắp ráp.