Các hàm trực tuyến (inline)
Việc tổ chức chương trình thành các hàm có 2 ưu điểm rõ rệt : Thứ nhất là chia chương trình thành các đơn vị độc lập, làm cho chương trình được tổ chức một cách khoa học dễ kiểm soát dễ phát hiện lỗi, dễ phát triển, mở rộng. Thứ hai ...
Việc tổ chức chương trình thành các hàm có 2 ưu điểm rõ rệt : Thứ nhất là chia chương trình thành các đơn vị độc lập, làm cho chương trình được tổ chức một cách khoa học dễ kiểm soát dễ phát hiện lỗi, dễ phát triển, mở rộng.
Thứ hai là giảm được kích thước chương trình, vì mỗi đoạn chương trình thực hiện nhiệm vụ của hàm được thay bằng một lời gọi hàm.
Tuy nhiên hàm cũng có nhược điểm là làm chậm tốc độ chương trình do phải thực hiện một số thao tác có tính thủ tục mỗi khi gọi hàm như: Cấp phát vùng nhớ cho các đối và biến cục bộ, truyền dữ liệu của các tham số cho các đối, giải phóng vùng nhớ trước khi thoát khỏi hàm.
Các hàm trực tuyến trong C++ cho khả năng khắc phục được nhược điểm nói trên.
Để biến một hàm thành trực tuyến ta viết thêm từ khoá
inline
vào trước khai báo nguyên mẫu hàm. Nếu không dùng nguyên mẫu thì viết từ khoá này trước dòng đầu tiên của định nghĩa hàm. Ví dụ:
inline float f(int n, float x); float f(int n, float x) { // Các câu lệnh trong thân hàm }
hoặc
inline float f(int n, float x) { // Các câu lệnh trong thân hàm }Trong mọi trường hợp, từ khoá inline phải xuất hiện trước các lời gọi hàm thì Trình biên dịch mới biết cần xử lý hàm theo kiểu inline.
Hàm f trong chương trình sau sẽ không phải là hàm trực tuyến vì từ khoá inline viết sau lời gọi hàm:
#include <conio.h>
#include <iostream.h>
void main()
{
int s ;
s = f(5,6);
cout << s ;
getch();
}
inline int f(int a, int b)
{
return a*b;
}
Chương trình dịch xử lý các hàm inline như các macro (được định nghĩa trong lệnh #define), nghĩa là nó sẽ thay mỗi lời gọi hàm bằng một đoạn chương trình thực hiện nhiệm vụ của hàm. Cách này làm cho chương trình dài ra, nhưng tốc độ chương trình tăng lên do không phải thực hiện các thao tác có tính thủ tục khi gọi hàm.
Dùng macro và hàm trực tuyến đều dẫn đến hiệu quả tương tự, tuy nhiên người ta thích dùng hàm trực tuyến hơn, vì cách này đảm bảo tính cấu trúc của chương trình, dễ sử dụng và tránh được các sai sót lặt vặt thường gặp khi dùng #define (như thiếu các dấu ngoặc, dấu chấm phẩy)
Phương án dùng hàm trực tuyến rút ngắn được thời gian chạy máy nhưng lại làm tăng khối lượng bộ nhớ chương trình (nhất là đối với các hàm trực tuyến có nhiều câu lệnh). Vì vậy chỉ nên dùng phương án trực tuyến đối với các hàm nhỏ.
Không phải khi gặp từ khoá inline là Trình biên dịch nhất thiết phải xử lý hàm theo kiểu trực tuyến.
Từ khoá inline chỉ là một sự gợi ý cho Trình biên dịch chứ không phải là một mệnh lệnh bắt buộc.Có một số hàm mà các Trình biên dịch thường không xử lý theo cách inline như các hàm chứa biến static, hàm chứa các lệnh chu trình hoặc lệnh goto hoặc lệnh switch, hàm đệ quy. Trong trường hợp này từ khoá inline lẽ dĩ nhiên bị bỏ qua.
Thậm chí từ khoá inline vẫn bị bỏ qua ngay cả đối với các hàm không có những hạn chế nêu trên nếu như Trình biên dịch thấy cần thiết (ví dụ đã có quá nhiều hàm inline làm cho bộ nhớ chương trình quá lớn)
Chương trình sau sử dụng hàm inline tính chu vi và diện tích của hình chữ nhật:
Phương án 1: Không khai báo nguyên mẫu. Khi đó hàm dtcvhcn phải đặt trên hàm main.
#include <conio.h>
#include <iostream.h>
inline void dtcvhcn(int a, int b, int &dt, int &cv)
{
dt=a*b;
cv=2*(a+b);
}
void main()
{
int a[20],b[20],cv[20],dt[20],n;
cout << " So hinh chu hat: " ;
cin >> n;
for (int i=1;i<=n;++i)
{
cout << " Nhap 2 canh cua hinh chu nhat thu " <<i<< ": ";
cin >> a[i] >> b[i] ;
dtcvhcn(a[i],b[i],dt[i],cv[i]);
}
clrscr();
for (i=1;i<=n;++i)
{
cout << " Hinh chu nhat thu " << i << " : ";
cout << " Do dai 2 canh= " << a[i] << " va " << b[i] ;
cout << " Dien tich= " << dt[i] ;
cout << " Chu vi= " << cv[i] ;
}
getch();
}
Phương án 2: Sử dụng khai báo nguyên mẫu. Khi đó từ khoá inline đặt trước nguyên mẫu.
#include <conio.h> #include <iostream.h> inline void dtcvhcn(int a, int b, int &dt, int &cv) ; void main() { int a[20],b[20],cv[20],dt[20],n; cout << " So hinh chu hat: " ; cin >> n; for (int i=1;i<=n;++i) { cout << " Nhap 2 canh cua hinh chu nhat thu " <<i<< ": "; cin >> a[i] >> b[i] ; dtcvhcn(a[i],b[i],dt[i],cv[i]); } clrscr(); for (i=1;i<=n;++i) { cout << " Hinh chu nhat thu " << i << " : "; cout << " Do dai 2 canh= " << a[i] << " va " << b[i] ; cout << " Dien tich= " << dt[i] ; cout << " Chu vi= " << cv[i] ; } getch(); } void dtcvhcn(int a, int b, int &dt, int &cv) { dt=a*b; cv=2*(a+b); }