Hàm inline và hàm template
Hàm inline
Phần tiêu đề “Hàm inline”Khi gọi một hàm, chương trình thường phải “nhảy” đến vị trí hàm đó trong bộ nhớ rồi quay lại - tốn một chút thời gian (overhead). Từ khóa inline gợi ý trình biên dịch chèn trực tiếp code của hàm vào nơi gọi, thay vì thực hiện một lời gọi hàm thực sự:
#include <iostream>
inline int square(int x) { return x * x;}
int main() { std::cout << square(5) << std::endl; // 25 // Trình biên dịch có thể "biến" dòng trên thành: std::cout << (5 * 5) << std::endl; return 0;}inline chỉ nên dùng cho các hàm rất ngắn gọn, được gọi thường xuyên (ví dụ: hàm getter/setter đơn giản). Với hàm dài, inline không giúp ích và có thể làm tăng kích thước file thực thi. Lưu ý: inline chỉ là một gợi ý (hint) - trình biên dịch có toàn quyền quyết định có áp dụng hay không.
Hàm template: viết code dùng chung cho nhiều kiểu dữ liệu
Phần tiêu đề “Hàm template: viết code dùng chung cho nhiều kiểu dữ liệu”Nếu không có template, để có hàm max cho cả int, double, std::string…, bạn sẽ phải viết nhiều phiên bản trùng lặp bằng cách nạp chồng (overloading). Template giải quyết vấn đề này bằng cách cho phép viết một hàm duy nhất dùng chung cho nhiều kiểu dữ liệu khác nhau.
#include <iostream>
template <typename T>T my_max(T a, T b) { return (a > b) ? a : b;}
int main() { std::cout << my_max(5, 10) << std::endl; // 10 (T là int) std::cout << my_max(3.5, 2.1) << std::endl; // 3.5 (T là double) std::cout << my_max<std::string>("abc", "abd") << std::endl; // abd (T là string)
return 0;}template <typename T>: khai báoTlà một kiểu dữ liệu “chưa xác định”, sẽ được trình biên dịch tự suy luận (hoặc chỉ định tường minh) khi hàm được gọi- Trình biên dịch tự động sinh ra một phiên bản hàm riêng cho mỗi kiểu dữ liệu thực sự được dùng - quá trình này gọi là template instantiation
Template với nhiều kiểu dữ liệu
Phần tiêu đề “Template với nhiều kiểu dữ liệu”#include <iostream>
template <typename T1, typename T2>void print_pair(T1 first, T2 second) { std::cout << first << " - " << second << std::endl;}
int main() { print_pair(1, "Mot"); // 1 - Mot print_pair(3.14, 'A'); // 3.14 - A return 0;}Chỉ định kiểu tường minh
Phần tiêu đề “Chỉ định kiểu tường minh”Thông thường trình biên dịch tự suy luận được kiểu T từ đối số truyền vào, nhưng đôi khi cần chỉ định rõ ràng:
template <typename T>T get_default() { return T(); // Giá trị mặc định của kiểu T}
int main() { int x = get_default<int>(); // 0 double y = get_default<double>(); // 0.0 return 0;}Template class (giới thiệu nhanh)
Phần tiêu đề “Template class (giới thiệu nhanh)”Không chỉ hàm, C++ còn cho phép tạo class template - đây chính là nền tảng của các container trong thư viện chuẩn như std::vector<T>, std::pair<T1, T2> mà bạn sẽ dùng ở các bài sau:
template <typename T>class Box {private: T value;public: Box(T v) : value(v) {} T get() { return value; }};
int main() { Box<int> int_box(42); Box<std::string> str_box("Hello");
std::cout << int_box.get() << std::endl; // 42 std::cout << str_box.get() << std::endl; // Hello
return 0;}Tổng kết
Phần tiêu đề “Tổng kết”inlinegợi ý trình biên dịch chèn trực tiếp code hàm vào nơi gọi, giảm overhead cho hàm ngắn được gọi thường xuyên- Template cho phép viết một hàm/class dùng chung cho nhiều kiểu dữ liệu, tránh lặp code do nạp chồng thủ công
- Trình biên dịch tự sinh ra phiên bản cụ thể cho mỗi kiểu dữ liệu thực sự được dùng (template instantiation)
std::vector,std::pair, và phần lớn thư viện chuẩn (STL) đều được xây dựng dựa trên template