• Thứ Năm, 03/12/2009 12:43 (GMT+7)

    Chuẩn C++ mới có gì mới

    Được biết đến với cái tên C++ 0x, chuẩn C++ mới hứa hẹn mang đến làn gió mới cho giới phát triển phần mềm.

    C++ (đọc là “C plus plus”) có thể nói là một trong những ngôn ngữ lập trình nổi tiếng nhất, có ảnh hưởng lớn cả trong giới công nghiệp lẫn giới học thuật. Hiện có hàng triệu lập trình viên sử dụng C++ để viết phần mềm cho nhiều loại máy móc. Nếu dùng máy tính, hầu như chắc chắn bạn có dùng một chương trình nào đó viết bằng C++. Hàng ngày, hầu như mọi người dùng máy tính và Internet đều có dùng chương trình viết bằng C++. Thậm chí, C++ còn được dùng để viết phần mềm điều khiển cho các thiết bị được cho là không có liên quan gì đến máy tính và lập trình như máy ảnh, thang máy.

    Thế giới phần mềm và phần cứng thay đổi nhanh và các ngôn ngữ lập trình phải phát triển để thích ứng. Sau hơn chục năm kể từ chuẩn ISO C++ đầu tiên (C++98, được phê chuẩn năm 1998), một chuẩn mới được biết đến với cái tên C++0x đang chuẩn bị ra mắt. Không như bản cập nhật năm 2003 (thường được gọi là C++03), C++0x là bước thay đổi lớn với nhiều tính năng mới quan trọng.

    Thông tin quan trọng cho các nhà phát triển làm việc với C++: các trình biên dịch phổ biến như C++ Builder (phiên bản 2009), Visual C++ (phiên bản 2010) và Gnu C++ (phiên bản 4.3) sẽ hỗ trợ chuẩn C++ mới. Hẳn bạn không muốn ngơ ngác khi nghe đồng nghiệp bàn luận về “lamda” hay “concept”. Giờ là lúc thích hợp để tìm hiểu chuẩn mới.

    Những tính năng then chốt

    Hai tính năng quan trọng nhất của C++0x là "concept" và xử lý song song.

    "Concept" cho phép lập trình viên xác định ràng buộc trên các tham số template, đây là cách thức để định nghĩa rõ ràng những kiểu mà một lớp hay hàm template sẽ chấp nhận.

    Ví dụ:

    “Ý tưởng của tôi là dùng các tiện ích của ngôn ngữ lập trình để giúp lập trình viên suy nghĩ một cách khác về thiết kế và hiện thực hệ thống. Tôi nghĩ rằng C++0x có thể làm được điều đó – và không chỉ cho các lập trình viên C++ mà còn cho cả các lập trình viên nói chung ...”
                                           Bjarne Stroustrup

    template requires LessThanComparable
    const T& min(const T &x, const T &y)
    { return y < x ? y : x; }

    Xác định hàm min() chỉ chấp nhận các kiểu hỗ trợ concept LessThanComparable. Sau đó LessThanComparable có thể được định nghĩa để kiểu đó hỗ trợ toán tử “<” (so sánh nhỏ hơn):

    auto concept LessThanComparable
    { bool operator<(T, T); }

    Concept hứa hẹn giúp cho việc lập trình và thiết kế tổng quát dễ dàng và tin cậy hơn nhiều.

    Không hề quá lời khi đề cập đến sự quan trọng của thư viện API song song chuẩn trong C++. Các bộ xử lý đa nhân ngày càng trở nên phổ biến do vậy bạn không thể trụ lại thời kỳ một nhân, hay đối phó bằng các thư viện API lệ thuộc nền tảng. Cuối cùng đã có thư viện song song hỗ trợ đa nền tảng, chuẩn và hiệu quả cho C++.

    Xét một ví dụ hết sức cơ bản: chương trình hiển thị dòng chữ “Hello World”.

    #include
    #include
    void hello()
    {
    std::cout<<"Hello (Concurrent) World"<<>
    }
    int main()
    {
    std::thread t(hello); t.join();
    }

    Xem bài giảng video về C++0x của giáo sư Bjarne Stroustrup tại http://www.catonmat.net/blog/bjarne-stroustrup-video-lecture-on-cpp-standard/

    "Lambda" và "closure" là tính năng nổi bật khác của C++0x. Lambda là một hàm “không tên” được định nghĩa tại nơi nó được gọi.

    Ví dụ:

    std::vector values = getValues();
    std::for_each( values.begin(), values.end(), [](int n) { cout << n << std::endl; } );

    Biểu thức lambda này được nhận biết bởi dấu hiệu [] theo sau là danh sách tham số nằm trong ngoặc đơn.

    Kiểu giá trị trả về có thể có hoặc không, đi sau ký hiệu ->.

    myfunc([](int x, int y) -> int {return x+y;} )

    Lambda có thể tham chiếu các biến trong phạm vi, ví dụ:

    std::vector values = getValues();
    int total = 0;
    std::for_each( values.begin(), values.end(), [&total](int n) { total += n } );

    Việc này được gọi là "sự đóng kín" (closure). Dĩ nhiên, bạn có thể thực hiện tương tự với hàm thông thường, nhưng lambda rõ ràng gọn hơn nhiều.

    ‘Tham chiếu rvalue’ là một cuộc cách mạng khác tuy khá thầm lặng. Có thể hầu hết người dùng sẽ không nhận biết sự tồn tại của nó, tính năng này cho phép những người thiết kế thư viện tối ưu container và thuật toán. Và các từ khóa mới ‘auto’ và ‘decltype’ cho phép gán kiểu tự động, chẳng hạn gán kiểu của một đối tượng khi khởi tạo. Đây là cách tuyệt vời để trình biên dịch chia sẻ gánh nặng lập trình.

    Nhiều quyền hơn

    Có các tính năng mới cung cấp cơ chế chuẩn và thống nhất cho việc kiểm soát môi trường biên dịch và thực thi bằng lập trình. Ví dụ, xét trường hợp địa chỉ bộ nhớ. Trong C++03 bạn phải dùng đến các kỹ thuật phụ thuộc nền tảng và trình biên dịch nếu bạn muốn can thiệp địa chỉ mặc định của dữ liệu. C++0x giới thiệu 2 toán tử mới alignof và alignas dùng để truy vấn và can thiệp các yêu cầu địa chỉ dữ liệu, ví dụ:

    Nhà nghiên cứu của AT&T, Bjarne Stroustrup đã xây dựng phiên bản C++ đầu tiên vào năm 1983. C++ kết hợp năng lực diễn đạt của lập trình hướng đối tượng (OOP - object-oriented programming) với tốc độ, sự cô đọng và linh hoạt của ngôn ngữ C – người tiền nhiệm do AT&T phát minh 10 năm trước. C++ hiệu quả như C và có thêm những tính năng cho phép tạo ra những phần mềm lớn hơn, dễ bảo trì hơn và có tính tin cậy cao hơn.

    Tại AT&T, C++ được “nhúng” trong các hệ thống truyền dẫn, chuyển mạch và điều khiển. C++ cũng được dùng trong lập trình khoa học, phân tích dữ liệu, mô phỏng...

    alignas (16) class Session
    {
    long long timestamp;
    int authorizations;
    bool active;
    //...
    };
    cout<< alignof(Session) <<>< font="">

    Nguyên tắc biểu thức hằng của chuẩn C++ hiện tại có nhiều hạn chế. Không giống "const", từ khoá mới "constexpr" đảm bảo biểu thức mà nó định nghĩa có thể được dùng như là biểu thức hằng, ví dụ trong khai báo mảng:

    constexpr int f(int x){
    return x * x; } //kiểm tra lúc biên dịch bắt buộc
    int arr[f(3)]; //OK, kích thước của mảng là 9

    Nói chung, "constexpr" báo cho lập trình viên biết một biểu thức hay đối tượng cụ thể được đánh giá và khởi tạo lúc biên dịch, ngược với "const" chỉ phát biểu đối tượng đó sẽ không thay đổi trạng thái sau khi khởi tạo.

    C++0x còn có một số tính năng mới khác nhằm làm đơn giản các công việc lập trình đệ quy và giảm thiểu mã lệnh rườm rà.

    Tương thích với các chuẩn khác

    C++0x tăng tính tương thích với các chuẩn quốc tế độc lập. Các bổ sung đầu tiên được thiết kế trong hợp đồng chặt chẽ với ISO/IEC 9899:1999 Standard C (viết tắt là C99).

    Ảnh hưởng của chuẩn Unicode 4.0 gần đây cũng được phản ánh trong C++0x. C++98 định nghĩa một kiểu ký tự đặt tên là wchar_t, kiểu này có kích thước được xác định khi hiện thực. Vào giữa thập niên 1990, người ta nghĩ rằng wchar_t đủ để hỗ trợ Unicode nhưng giờ không còn đúng. Kích thước không xác định của wchar_t không cho phép việc mã hóa UTF hỗ trợ nhiều nền tảng trong C++98. C++0x giải quyết vấn đề này bằng cách đưa ra 2 kiểu ký tự mới có kích thước chuẩn: char16_t và char32_t được thiết kế đặc biệt để hỗ trợ tất cả bộ mã Unicode 4.0 và các lược đồ mã hoá (UTF-8, UTF-16 và UTF-32). Tất nhiên, nó cũng hỗ trợ chuỗi Unicode trong Standard Library.

    Chuẩn C99 cũng có giới thiệu kiểu "long long" để xử lý số nguyên 64-bit. C++0x khắc phục sự không tương thích của kiểu này bằng cách đưa "long long"và "unsigned long long" vào danh sách các kiểu cơ bản.

    Mở rộng thư viện

    Standard Library của C++0x được mở rộng rất nhiều. Dưới đây chỉ liệt kê những cái nổi bật.

    Tham khảo:
    • C++0x: The Dawning of a New Standard, DevX
    • A Brief Look at C++0x, Bjarne Stroustrup
    • The Future of C++0X, InformIT
    • The C++ Standards Committee, http://www.open-std.org/jtc1/sc22/wg21/

    Một thư viện mới để thao tác "regular expression" được định nghĩa trong header . Không hỗ trợ regular expression là thiếu sót đáng kể của C++, đặc biệt đối với giới lập trình web, những người thiết kế XML parser và các ứng dụng xử lý chuỗi khác.

    Trở lại năm 1997, ràng buộc thời gian đã không cho phép Ủy ban Chuẩn đưa hash table vào chuẩn C++ đầu tiên. Chuẩn C++ mới khắc phục điều này bằng cách thêm 4 container: std::unordered_map, std::unordered_multimap, std::unordered_set và std::unordered_multiset.

    Có lẽ mở rộng Standard Library nổi bật nhất là các lớp con trỏ thông minh: std::tr1::shared_ptr và người anh em ít được biết đến, std::tr1::weak_ptr.

    Về thuật toán, 11 thuật toán mới được đưa ra, một số trong số đó sửa các lỗi trong chuẩn C++98, trong khi một số khác làm đơn giản hóa các tác vụ thông dụng. Có thể kể một số như:

    • all_of( first, last, pred): Trả về giá trị true nếu tất cả phần tử trong dãy thỏa thuộc tính pred.

    • any_of( first, last, pred): Trả về true nếu có bất kỳ phần tử trong dãy thỏa pred.

    • copy_n( first, n, result): Sao chép n phần tử vào result.

    • Iota( first, last, value): Với từng phần tử trong dãy, hàm này gán giá trị value và tăng trước value bằng ++value.

    • None_of( first, last, pred): Trả về giá trị true nếu không có phần tử nào trong dãy thỏa pred.

    Cuối cùng, các template phạm vi (range) của C++0x gắn cặp với "interator" (lặp vòng), nhờ vậy đơn giản đáng kể các tác vụ tuần tự và làm gọn nhiều thuật toán phổ biến.

    Đường dài phía trước

    C++0x không phải là ngôn ngữ lập trình mới. Lập trình viên C++ không phải lo vì chuẩn mới sẽ tương thích 100% với chuẩn C++ hiện tại, theo lời giáo sư Bjarne Stroustrup, người tạo ra C++ và là thành viên của Ủy ban ISO C++.

    Đến giờ hẳn những người quan tâm đến C++ đều đã biết tin về cuộc họp tại Frankfurt (Đức) hồi tháng 7: Ủy ban ISO C++ đã biểu quyết gỡ bỏ "concept" khỏi C++0x vì lý do "chưa hoàn thiện" . Điều này gây thất vọng cho nhiều người, trong đó có giáo sư Bjarne Stroustrup, người rất tâm huyết với "concept". Việc hoàn thiện ‘concept’ có thể phải mất vài năm.

    Ngay cả không có "concept" thì C++0x vẫn là cải tiến đáng kể so với chuẩn C++ hiện tại (C++98). Theo kế hoạch thì Ủy ban Chuẩn sẽ nhóm họp tiếp vào cuối năm nay để phê chuẩn chính thức và đưa ra sử dụng chuẩn C++ mới (và C++0x sẽ thành C++09). Tuy nhiên đến thời điểm thực hiện bài viết này vẫn chưa có động tĩnh gì. Nhiều khả năng chúng ta sẽ có C++10 hay C++0A (nếu Ủy ban Chuẩn thích dùng số hệ thập lục phân!).

    Nguyễn Lê

    ID: A0911_82