22 điểm bởi GN⁺ 22 ngày trước | 6 bình luận | Chia sẻ qua WhatsApp
  • C++26 đã chính thức hoàn tất về mặt kỹ thuật. Gồm bốn tính năng cốt lõi: reflection, tăng cường an toàn bộ nhớ, Contracts, std::execution
  • Compile-time reflection là động cơ trừu tượng hóa mạnh mẽ nhất trong lịch sử C++ kể từ khi template ra đời, cho phép ngôn ngữ tự mô tả chính nó và sinh mã
  • Chỉ cần biên dịch lại mã C++ hiện có bằng C++26 là có thể loại bỏ hành vi không xác định (UB) do biến cục bộ chưa khởi tạo, đồng thời thư viện chuẩn được tăng cường đảm bảo an toàn bounds
  • Theo kết quả triển khai tại Google, đã sửa hơn 1.000 lỗi và ghi nhận mức giảm 30% segfault trong môi trường production
  • Dự kiến các trình biên dịch sẽ nhanh chóng tiếp nhận, khi GCC đã hợp nhất reflection và contracts vào trunk

C++26 hoàn tất: Bản phát hành quan trọng nhất kể từ C++11

  • Tại cuộc họp ủy ban ISO C++ tổ chức ở Croydon, London, Vương quốc Anh, công việc kỹ thuật của C++26 đã được hoàn tất cuối cùng
    • Khoảng 210 người tham dự (130 trực tiếp, 80 từ xa qua Zoom), với đại diện chính thức từ 24 quốc gia
    • Phần lớn thời lượng cuộc họp được dành để xử lý 411 bình luận quốc tế (giai đoạn CD) được gửi trong mùa hè
    • Tập trung vào hoàn thiện chi tiết cuối cùng (fit-and-finish), không thêm hay loại bỏ tính năng mới
  • C++26 được chốt tại kỳ họp này đã bước vào giai đoạn chuẩn bị tài liệu cuối cùng cho bỏ phiếu phê duyệt quốc tế (DIS)

4 tính năng cốt lõi của C++26

(1) Reflection

  • Đây là bản nâng cấp lớn nhất trong lịch sử phát triển C++ kể từ khi template được phát minh, cho phép ngôn ngữ tự mô tả chính nó và sinh mã
  • Vào tháng 6/2025, ủy ban C++ đã đưa compile-time reflection vào bản nháp C++26, đánh dấu bước ngoặt trong lịch sử ngôn ngữ
  • Tính năng này được giới thiệu là "động cơ mới mạnh mẽ nhất để biểu đạt các trừu tượng hiệu quả, và sẽ cần thêm 10 năm nữa để khám phá hết tên lửa này có thể làm được gì"

(2) Tăng cường an toàn bộ nhớ

  • Chỉ cần biên dịch lại, toàn bộ nhóm UB do đọc biến cục bộ chưa được khởi tạo trong mã C++ hiện có sẽ được loại bỏ trong C++26
  • Hardened Standard Library đã được chuẩn hóa, đảm bảo an toàn bounds cho các kiểu quan trọng như vector, span, string, string_view
    • Mức overhead hiệu năng đo được trung bình chỉ 0,3% (dưới 1%)
    • Đã được triển khai trên hàng trăm triệu dòng mã tại nền tảng Apple và các dịch vụ của Google
  • Các số liệu từ triển khai tại Google:
    • Đã sửa hơn 1.000 lỗi
    • Dự kiến ngăn chặn 1.000~2.000 lỗi mỗi năm
    • Tỷ lệ segfault giảm 30% trên toàn bộ production
    • Trong toàn bộ mã C++ của Google, chỉ có 5 dịch vụ opt-out hoàn toàn và chỉ 7 vị trí dùng API truy cập không an toàn

(3) Contracts: pre, post, contract_assert

  • C++26 đưa vào tính năng contracts ở cấp ngôn ngữ — hỗ trợ precondition, postcondition và câu lệnh assertion trong khai báo hàm
  • Được đánh giá là mạnh hơn rất nhiều so với macro assert của C
  • Kết quả bỏ phiếu khi thông qua contracts:
    • Tháng 2/2025 (hợp nhất vào working draft): 100 phiếu thuận, 14 phiếu chống, 12 phiếu trắng
    • Tháng 3/2026 (chốt cuối cùng cho C++26): 114 phiếu thuận, 12 phiếu chống, 3 phiếu trắng
  • Dù một số chuyên gia trong ủy ban vẫn tiếp tục nêu lo ngại kỹ thuật, chủ đề này đã được thảo luận đầy đủ qua 3 kỳ họp và nhiều cuộc họp điện thoại
  • Trước kỳ họp tháng 11/2025, đã hoàn tất sửa 2 lỗi trong đặc tả contracts để phản ánh phản hồi

(4) std::execution (Sender/Receiver)

  • Đây là mô hình bất đồng bộ của C++, một framework thống nhất để biểu đạt và kiểm soát tính đồng thời cùng song song
  • Cho phép viết structured concurrency (mô hình đồng thời có vòng đời lồng nhau chặt chẽ) dễ dàng hơn, từ đó có đặc tính an toàn giúp ngăn data race về mặt cấu trúc
  • Lưu ý: hiện tài liệu còn thiếu và hệ sinh thái thư viện "fingers-and-toes" còn chưa đầy đủ, nên mức độ khó khi áp dụng cao hơn các tính năng C++ khác
    • Có thể cần sự hỗ trợ của chuyên gia đã quen thuộc với mô hình này, cũng như cần viết thư viện adapter để tích hợp với mã bất đồng bộ hiện có

Vì sao C++26 được kỳ vọng sẽ được tiếp nhận nhanh chóng

  • Đây là bộ tính năng được mong đợi nhất kể từ C++11, vì bao gồm reflection và tăng cường an toàn — những thứ đa số lập trình viên C++ sẽ dùng hằng ngày
    • Các tính năng như Parallel STL, concepts, coroutines, modules trong C++17, C++20, C++23 được đánh giá là chưa tạo ảnh hưởng rộng đến mọi lập trình viên C++ như C++11
  • GCC và Clang trong suốt quá trình phát triển C++26 đã duy trì trạng thái triển khai sẵn trước khoảng hai phần ba số tính năng
    • GCC đã hợp nhất reflection và contracts vào trunk, chỉ còn chờ phát hành

Bắt đầu công việc cho C++29: đào sâu an toàn bộ nhớ

  • Tại kỳ họp này, lịch trình C++29 cũng đã được thông qua, tiếp tục chu kỳ phát hành 3 năm
  • Trọng tâm chính của C++29 được xác định là tăng cường hơn nữa an toàn kiểu và an toàn bộ nhớ
    • Đang xem xét các đề xuất nhằm tiếp tục giảm hành vi không xác định (UB)
    • SG23 (nhóm con về an toàn và bảo mật) đang làm việc dựa trên P3984 hồ sơ an toàn kiểu của Bjarne Stroustrup và framework hồ sơ tổng quát của Gabriel Dos Reis
  • Oliver Hunt của Apple đã trình bày P4158R0 "Subsetting and Restrictions for C++ for Memory Safety"
    • Áp dụng cách tiếp cận subset-of-superset cho hơn 4 triệu dòng mã của WebKit
    • Báo cáo cho biết cách này "chặn được nhiều lớp lỗ hổng và chính sách hiện tại lẽ ra đã ngăn phần lớn các exploit trong quá khứ"
  • Chủ đề an toàn bộ nhớ đã được thảo luận chuyên sâu tại phiên tối thứ Tư với hơn một nửa ủy ban tham dự và phiên EWG chuyên đề chiều thứ Sáu với khoảng 90 người tham gia
  • Thư viện quantities and units (P3045R7 "Quantities and units library") đã tiến từ SG6·SG18 lên LEWG (nhóm con tiến hóa thư viện chính)

Lịch trình sắp tới

  • Hai kỳ họp tiếp theo sẽ được tổ chức tại Brno, CH Czech (tháng 6)Búzios, Rio de Janeiro, Brazil (tháng 11)
  • Trong hai kỳ họp này sẽ bắt đầu bổ sung tính năng vào working draft của C++29
  • Từ nay đến trước kỳ họp tiếp theo, nhiều buổi telecon của các nhóm con đã được lên lịch

6 bình luận

 

zzz

 
Ý kiến trên Hacker News
  • Thật đáng tiếc khi tính năng Contracts đã được đưa vào chuẩn của C++
    Cảm giác như lại bổ sung thêm một lớp phức tạp nữa vào một ngôn ngữ vốn đã chạm tới giới hạn về độ phức tạp
    Ngay cả Bjarne Stroustrup cũng gọi tính năng này là "một thiết kế chưa hoàn thiện và bị thổi phồng theo kiểu ủy ban"
    Tôi cũng cho rằng bản thân tính năng này có quá nhiều yếu tố nguy hiểm (footgun), nên khó thấy được tính chính đáng của nó

    • Tôi từng tự triển khai một phần mở rộng Contracts cho C++ vào đầu những năm 90
      Nhưng chẳng ai tỏ ra quan tâm
      Tài liệu liên quan có ở đây
    • Nhiều người nói “C++ quá phức tạp”, nhưng điều thú vị là mỗi người lại hình dung ra một tính năng phức tạp khác nhau
    • Thiết kế Contracts của C++ có thể sai, nhưng tôi nghĩ bản thân khái niệm này là điều ngôn ngữ rất cần để phát triển
      Đây là yếu tố cốt lõi để tích hợp với kiểm chứng hình thức (proof assistant) như Ada hay Rust, cho phép xác minh tĩnh thay cho kiểm thử
      Có thể tham khảo Ada Spark
    • Tài liệu về Contracts quá rối rắm
      Ví dụ đầu tiên trong tài liệu cppreference lại là một trường hợp ngoại lệ có thay đổi trạng thái
      Cú pháp cũng không trực quan
      Ví dụ, dạng như asserts_pre(num >= 0) sẽ rõ ràng hơn nhiều so với pre(num >= 0)
      Nhưng có vẻ họ ưu tiên sự ngắn gọn
    • Contracts thực ra chỉ là chuẩn hóa những gì các lập trình viên C++ vốn đã làm một cách không chính thức
      Thay vì làm tăng thêm độ phức tạp, nó là hướng hợp nhất những cách mỗi người tự triển khai để cải thiện khả năng tương tác
      Ngược lại, tôi cho rằng những tính năng như Reflection mới là thứ làm tăng độ phức tạp hơn
  • Với tư cách là một lập trình viên C# và Java, tôi có một điều muốn hỏi
    Dạo này người ta dùng C++ để làm những loại ứng dụng nào?
    Tôi hiếm khi có cơ hội nghe về việc nó thực sự đang giải quyết những vấn đề gì

  • Việc định nghĩa lại “erroneous behavior” cho biến chưa khởi tạo khá thú vị
    Theo tài liệu chuẩn, điều này tạo ra chi phí runtime,
    và có thể chuyển lại thành undefined behavior bằng thuộc tính [[indeterminate]]

    int x [[indeterminate]];
    std::cin >> x;
    
    • Ngôn ngữ D tự động khởi tạo mọi biến
      Nếu thực sự không muốn khởi tạo thì phải viết rõ ràng như int x = void;
      Gần như không thể vô tình viết như vậy
    • Tôi đọc lướt tài liệu thì có hai điều gây ngạc nhiên
      1. “giá trị được quyết định độc lập” chính xác là gì thì không rõ — là điền 0 hay là một giá trị ngẫu nhiên trong bộ nhớ?
      2. Tôi không hiểu vì sao [[indeterminate]] lại quay về UB (Undefined Behavior)
    • Có lẽ tính năng này sẽ được điều khiển bằng cờ của compiler
      Một số dự án có thể vẫn sẽ thích khởi tạo thủ công
    • Nghĩ tới người sau này sẽ nhìn thấy [[indeterminate]] trong code mà thấy kinh khủng
      Cuối cùng họ либо sẽ mất thời gian đi tra ý nghĩa của nó, hoặc về sau просто mặc kệ
      Điều này làm tôi nhớ đến trải nghiệm đọc code Rust với quá nhiều generic và trait khiến rất khó theo dõi
  • Tôi từng làm ở đội C++ của Microsoft vào những năm 90
    Khi đó tôi nghĩ RTTI đã là giới hạn của hệ thống phản chiếu (reflection) mà C++ có thể có
    Sự phát triển bây giờ thật đáng kinh ngạc

  • Việc tổ chức cuộc họp ở Croydon rồi không cho ai rời đi cho tới khi ký tên đúng là một chiến thuật khá khôn khéo
    Tôi không muốn làm việc ở đó thêm lần nào nữa

  • Tôi tò mò về tình trạng triển khai C++26 của GCC và Clang
    GCC đã hợp nhất reflection và contracts vào trunk rồi, nhưng không rõ Clang đang ở mức nào

    • Trang trạng thái của Clang ghi cả hai là “no”,
      còn trang của GCC thì ghi “yes”
    • Bloomberg đã công khai một bản triển khai reflection cho Clang ở đây
      Nó đã dùng được trên Compiler Explorer, và đang được tận dụng để bổ sung reflection cho simdjson
  • Tôi nghi ngờ những thay đổi ở hệ thống module trong chuẩn lần này có thực sự khiến nó được dùng rộng rãi hơn không

    • Tôi nghĩ ít nhất một lần C++ WG nên tập trung vào module và packaging hơn là tính năng mới
      Đó chính là lý do Cargo của Rust vượt xa C++
      Việc không thể chỉ dùng một dòng cargo add để thêm dependency đang khiến thế hệ mới tránh xa nó
    • Phần lớn compiler vẫn chưa hỗ trợ header unit
      Nếu CMake áp dụng mô hình biên dịch 2 giai đoạn của Clang thì tốc độ build sẽ được cải thiện đáng kể,
      và khi đó module mới thực sự bắt đầu được chấp nhận rộng rãi
    • Tôi nghĩ module vốn đã là một ý tưởng thất bại
      Gần như không có khả năng trở thành dòng chính
    • Thành thật mà nói, giờ tôi chỉ muốn việc phát triển C++ dừng lại
      Có quá nhiều tính năng mới nên rất khó theo kịp
      Hệ thống build cũng lộn xộn, và file header thì giờ đáng ra phải biến mất rồi
  • Hơi lệch chủ đề, nhưng cách nói “London Croydon” nghe khá lạ
    Bình thường chẳng phải nên nói “Croydon, London” sao?

    • Cũng có những cách đảo ngược phổ biến như “London Gatwick Airport”
      Khi lên kế hoạch du lịch, đọc từ khu vực lớn tới khu vực nhỏ thường tự nhiên hơn
    • Mỗi người có xu hướng khác nhau: nói từ cái cụ thể trước hay từ cái tổng quát trước
      Có lẽ họ viết “London, Croydon” để tạo cảm giác là “cuộc họp diễn ra ở London”
      “Croydon, London” lại nghe giống “diễn ra ở Croydon, vùng ngoài London”, nên kém sang hơn — một cách diễn giải nửa đùa nửa thật
  • Cũng có những phản ứng mỉa mai kiểu như “nó ra đời đúng lúc ngay trước khi ngôn ngữ này bị khai tử”

  • Nếu C++29 chỉ tập trung vào cải thiện chất lượng và gọt giũa các tính năng hiện có thì có lẽ cộng đồng cũng sẽ không quá bất mãn

    • Cá nhân tôi thì chỉ cần C++29 có thêm một hàm random() một dòng là đã thấy hài lòng rồi
    • Tất nhiên phản ứng của cộng đồng sẽ còn tùy vào việc những tính năng nào được bổ sung
 

Thay vì bổ sung thêm tính năng để đảm bảo an toàn bộ nhớ, chỉ cần không cho phép con trỏ treo hoặc tham chiếu có thể thay đổi thì an toàn bộ nhớ cũng đã được cải thiện, vậy mà họ lại chỉ làm tăng độ phức tạp của mã bằng cách thêm tính năng.

 

Tôi đã rất vất vả mới chuyển sang Rust, nên việc khá nhiều tính năng tôi từng chờ đợi đã được đưa vào bản tiêu chuẩn C++26 đúng là đáng khích lệ. Nhưng tôi sẽ không quay lại C++ đâu... haha

 

Phần liên quan đến đóng gói cũng đang được phía CMake đưa ra..
https://www.kitware.com/common-package-specification-is-out-the-gate/

 

contract đúng là tính năng tôi đã chờ đợi bấy lâu, cuối cùng cũng đã có