Lời mở đầu Trong thế giới lập trình hiện nay, việc tiếp cận và ứng dụng các công cụ hiệu quả có vai trò thiết yếu trong việc đạt được hiệu suất cao và tối u hóa quá trình phát triển phần mềm. C+-+ từ lâu được đánh giá là ngôn ngữ mạnh vì tính gần gũi với ngôn ngữ máy. Một trong những công cụ mạnh mẽ nhất được cung cấp cho ngôn ngữ lap trinh C++ chinh 1a Standard Template Library (STL) dude thiét ké béi Alexander Stepano. STL khéng chi là một thư viện, mà còn là một triết lý lập trình, nơi mà khái niệm lập trình tong quat (generic programming) được thể hiện rõ nét nhất thông qua các template.
Thư viện này bao gồm một bộ sưu tập các container, thuật toán, và iterators, được thiết kế để hỗ trợ người lập trình trên nhiều khía cạnh từ quản lý dữ liệu đến xử lý thuật toán phức tạp. Khởi nguồn từ nhu cầu lập trình không phụ thuộc vào kiểu dữ liệu, #TL đã cách mạng hóa cách thức xây dựng các chương trình C++- bằng cách cung cấp một loạt các cấu trúc dữ liệu (như vector, queue, list, map,.) và thuật toán (như sort, search, transform,.) có thể tái sử dụng trên nhiều loại dữ liệu. Điều này không chỉ làm giảm bớt thời gian phát triển phần mềm mà còn tăng cường độ tin cậy và hiệu năng của chương trình. STL cung cấp các giải pháp lập trình tổng quát mà không làm mất đi hiệu suất vốn có của C-L+, một yếu tố quan trọng mà người lập trình không thể bỏ qua.
Điều này làm cho STL trở thành công cụ không thể thiếu đối với những lập trình viên C-+-+, từ những người mới bắt đầu cho đến các chuyên gia, những người tham gia vào các cuộc thi lập trình và những người làm việc trong lĩnh vực nghiên cứu phát triển. Qua bài báo cáo, nhóm sẽ khám phá sâu rộng về từng thành phần của STL, hiểu rõ về cách thức hoạt động của chúng và cách chúng có thể được ứng dụng để giải quyết các vấn đề lập trình phức tạp, qua đó nâng cao kỹ năng và hiểu biết của người lập trình về một trong những thư viện mạnh mẽ nhất trong C-L+. Trang 4 Trường Đại học Khoa học Tự nhiên - ĐHQG HCM 2_ Lịch sử hình thành [15] Bồi cảnh hình thành Alexander Stepanov nhan ra tâm quan trọng và tiềm năng của lập trinh tong quat (generic programming), trudc đó ông cùng đồng nghiệp đã phát triển một thư viện Ada , tuy nhiên Ada không được sử dụng rộng rãi trong công chúng, bên cạnh đó nhận ra C-+-+ sẽ được sử dụng rộng rãi trong công chúng hơn và hỗ trợ tốt cho việc lập trình tổng quát cũng nhĩ khả năng truy cập linh hoạt vào bộ nhớ thông qua con trỏ, điều quan trọng giúp đạt được tính tổng quát mà không làm giảm hiệu quả của ngôn ngữ. Khởi Nguyên Đầu thập niên 90: STL được phát triển bởi Alexander Stepanov.
Trong quá trình làm việc tại HP (Hewlett- Packard) Labs, Stepanov đã phối hợp cùng Meng Lee để tạo ra STL. Cảm hứng của Stepanov đến từ niềm tin rằng các thuật toán và cấu trúc dữ liệu nên được tách biệt rõ ràng với các loại dữ liệu mà chúng xử lý. Định Hình và Phát Triển Năm 1994: Stepanov và Lee hoàn thành phiên bản đầu tiên của TL, và bắt đầu giới thiệu nó vào C-+-+-. Sự chấp nhận của STL trong tiêu chuẩn C-+-+ là một phần của nỗ lực nhằm thêm tính năng lập trình khái quát vào ngôn ngữ này.
Cuối những năm 1990: STL duge chính thức hợp nhất vào ANSI/ISO C++ Standard Library. Sự hợp nhất này không chỉ đánh dấu việc chấp nhận rộng rãi các khái niệm của lập trình khái quát mà còn thể hiện qua, việc sử dụng rộng rãi các templates. Sự Hội Tụ và Chuẩn Hóa Năm 1998: C++ Standard được chính thức công bố, trong đó bao gồm TL như một phần cốt lõi. Điều này đã thiết lập một chuẩn mực cho các nhà phát triển phần mềm, thúc đẩy sự ổn định và khả năng tương thích giữa, các trình biên dịch.
Những năm 2000 đến nay: TL tiếp tục được mở rộng và cải tiến trong các phiên bản tiếp theo của chuẩn C-+L-+, với cdc cép nhat quan trong trong C++11, C+414, C++4+17 va cdc phién ban sau nay. Cac cải tiến bao gồm việc bổ sung các container mới, thuật toán, và cải thiện hiệu suất. Tác Động và Di Sản STL không chỉ ảnh hưởng tới cách thức các chương trình C+-+ được viết mà còn ảnh hưởng đến nhiều ngôn ngữ lập trình khác trong việc hỗ trợ lập trình khái quát. Nó cũng là một ví dụ điển hình về ảnh hưởng của lý thuyết toán học và lập trình hàm đến thế giới lập trình thực tế, làm thay đổi quan điểm về thiết kế và triển khai phần mềm.
Nhờ vào sự phát triển của STL, các lập trình viên có thể viết code ngắn gọn, hiệu quả hơn, và có thể tái sử dụng một cách rộng rãi, góp phần làm nền tảng cho các phát triển sau này trong lập trình hiện đại. Trang 5 Trường Đại học Khoa học Tự nhiên - ĐHQG HCM 3 Kiền trúc của thư viện Thr vién STL gém 5 loại thành phần chính: e Iterator: Là đối tượng giống con trỏ được sử dụng để truy cập vào từng mục dữ liệu (thường được gọi là các phần tử) trong một container. Thong thường, chúng được sử dụng để di chuyển tuần tự từ phần tử này sang phần tử khác, quá trình này được gọi là lặp qua container. e Container: Là một cách để lưu trữ dữ liệu, cho dù dữ liệu đó bao gồm các kiểu dữ liệu cơ bản như int và float, hay các đối tượng của lớp.
e Algorithm: Cung cấp các thuật toán như sort, ñnd,. Được sử dụng để thao tác dữ liệu lưu trữ trong container, những cũng có thể áp dụng chúng cho các mảng thông thường. e Function object /Functors: Đóng gói một hàm vào một đối tượng để sử dụng bởi các thành phần khác. Cung cấp một cách để truyền hàm vào thuật toán, cho phép tùy chỉnh hình vi của nó.
e Adapter: Là các lớp mẫu giúp tạo ra các interface mới cho các container, cho phép chúng ta tương tác với các container, iterator va ham theo những cách mới và linh hoạt hơn. Việc phân chia thành 5 thành phần như vậy giúp giảm thiểu đáng kể không gian thành phần. Ví dụ, xem xét về việc cũng cấp một ham tìm kiếm cho mỗi loại container, nếu không có thư viên STL thì có thể sẽ phải viết một hàm tìm kiếm riêng cho mỗi loại container (VD: Mắng, list, queue,. Kiến tốn thời gian và công sức, còn tạo ra nhiều mã nguồn có thể gây lỗi.
Với STL, chỉ cần cung cấp một phiên bản tìm kiếm duy nhất, hàm này hoạt động với mọi lại container, miếm là chúng đáp ứng một tập hợp cơ ban các yêu cần (VD: Chúng cung cấp một iterator) Giúp giảm đáng kể số lượng mã cần viết đồng thời tăng khả năng tái sử dụng mã. Nếu các thành phần của phần mềm được biểu diễn dưới dạng một mảng ba chiều, nơi một chiều đại diện cho các kiểu dữ liệu khác nhau (ví dụ: imt, double,.), chiều thứ hai đại diện cho các container khác nhau (ví dụ: vector, linked-list, file,.), và chiều thứ ba đại diện cho các thuật toán khác nhau trên các container (ví du: search, sort,.), néu 2, j, và & là kích thước của các chiều, thì ¿ x j + & phiên bản mã khác nhau phải được thiết kế. Bằng cách sử dụng các hàm mẫu được tham số hóa bởi một kiểu dữ liệu, thì chỉ cần 7 + & phiên bản. Hơn nữa, bằng cách làm cho các thuật toán hoạt động trên các container khác nhau, Thì chỉ cần 7 + k phiên bản.
Điều này đơn giản hóa đáng kể công việc thiết kế phần mềm và cũng làm cho việc sử dụng các thành phần trong thư viện cùng với các thành phần do người dùng định nghĩa một cách rất linh hoạt. Người dùng có thể dễ dàng định nghĩa một lớp container chuyên biệt và sử dụng hàm sắp xếp của thư viện để sắp xếp nó. Người dùng có thể cung cấp một hàm so sánh khác cho việc sắp xếp hoặc như một con trổ thông thường đến một hàm so sánh, hoặc như một đối tượng hàm (một đối tượng với operator() được định nghĩa) thực hiện các so sánh. Thư viện mở rộng các mô hình Ở + + cơ bản một cách nhất quán, vì vậy người lập trình Ở/Œ + + có thể dễ dàng bắt đầu sử dụng thư viện.
Ví dụ, thư viện chứa hàm mẫu merge. Khi người dùng có hai mảng và b cần được hợp nhất vào mảng c, có thể được thực hiện như sau: Trang 6 Trường Đại học Khoa học Tự nhiên - ĐHQG HCM #include <iostream> #include <algorithm> “ 4 using namespace std; 6 int main(}){ 8 int a[3] = {1, 2, 3}; 9 int b[3] = {4, 5, 6}; 10 int c[6]; 11 merge(a, a + 3, b, b+ 3, c); 12 18 for(int i = 0; i < 6; i++) f 14 cout << c[i] << " "; 15 } 16 return 0; 17 + Dutput: 1 2 3 45 6 Nếu người dùng muốn hợp nhất một vector a và một list b vào một mảng c chưa được cấp phát thì có thể được thực hiện như sau: 1 #include <iostream> 2 #include <algorithm> 3 #include <vector> 4 #include <list> 6 using namespace std; s int main(Q)f{ 10 vector<int> a = {1, 2, 3}; " list<int> b = {4, 5, 6}; 12 int *c = new int[a.end(), c); 15 for(int i = 0; i < a.size(); i++){ 16 cout << c[i] << " "; 17 + 18 19 + 1 Dutput: 12345 6 Trang 7 Trường Đại học Khoa học Tự nhiên - ĐHQG HCM Trong nhiều trường hợp, việc lặp qua các luồng nhập/xuất (H/O streams) giống như lặp qua các cấu trúc dữ liệu thông thường (như mắng, danh sách, v.) rất hữu ích. Điều này đặc biệt hữu ích khi muốn thao tác với dữ liệu từ một nguồn đầu vào (như một tệp hoặc luồng nhập chuẩn), và san đó ghỉ kết quả vào một nguồn đầu ra (như một tệp khác hoặc luồng xuất chuẩn), mà không cần tạo một cấu trúc dữ liệu tạm thời để lưu trữ kết quả. Thư viện STL trong Ở + + cung cấp hai lớp mẫu, isiream iterator và ostream iterator, để hỗ trợ việc này.
Cả hai lớp này đều cho phép sử dụng các thuật toán STL với các luồng I/O như thể chúng là các cấu trúc dữ liệu thông thường. Dưới đây là chương trình đọc các số từ một tệp, sau đó sắp xếp và ghi chúng ra một tệp khác: #include <iostream> #include <iterator> #include <fstream> #include <vector> #include <algorithm> using namespace std; int main() { ifstream inputFile("input.txt"); ofstream outputFile ("output.txt"); istream_iterator<int> start (inputFile), end; vector<int> numbers(start, end); ostream_iterator<int> out(outputFile, “ "); copy (numbers.