close up photo of programming of codes

codecungnhau.com

Một trang web về kỹ thuật lập trình

Hiểu về constexpr trong C++

constexpr là một tính năng mới được thêm vào trong C++11. Ý tưởng chính là cải thiện hiệu suất của các chương trình bằng cách thực hiện tính toán tại thời điểm biên dịch thay vì lúc thực thi. Lưu ý rằng một khi chương trình được nhà phát triển biên dịch và hoàn thiện, nó sẽ được chạy nhiều lần bởi người dùng. Ý tưởng là dành thời gian cho biên dịch và tiết kiệm thời gian khi thực thi.

constexpr xác định giá trị của một đối tượng hoặc hàm tại lúc biên dịch và là biểu thức có thể được sử dụng trong các biểu thức hằng khác. Ví dụ trong chương trình dưới đây, product() được tính toán tại thời điểm biên dịch.

// constexpr function for product of two numbers. 
// By specifying constexpr, we suggest compiler to 
// to evaluate value at compile time 
constexpr int product(int x, int y) 
{ 
	return (x * y); 
} 
int main() 
{ 
	const int x = product(10, 20); 
	cout << x; 
	return 0; 
} 

Khi môt hàm được khai báo là constexpr,

  • Trong C++11, một hàm constexpr chỉ nên chứa một câu lệnh return; C++14 cho phép nhiều hơn một câu lệnh.
  • Hàm constexpr chỉ nên tham chiếu đến các biến toàn cục hằng.
  • Hàm constexpr chỉ có thể gọi hàm constexpr khác chứ không phải hàm thông thường.
  • Hàm không được có kiểu void và một số toán tử như tăng tiền tố (++v) không được phép trong hàm constexpr.

Hàm constexpr với hàm inline

Cả hai đều nhằm cải thiện hiệu suất, các hàm inline yêu cầu trình biên dịch mở rộng tại thời điểm biên dịch để tiết kiệm thời gian và chi phí gọi hàm. Trong các hàm inline, các biểu thức luôn được tính toán trong thời gian chạy. constexpr thì khác, các biểu thức này được tính tại thời điểm biên dịch.

Ví dụ về cải thiện hiệu suất của constexpr

// A C++ program to demonstrate the use of constexpr 
#include<iostream>
using namespace std;
constexpr long int fib(int n) 
{ 
	return (n <= 1)? n : fib(n-1) + fib(n-2); 
}
int main () 
{ 
	// value of res is computed at compile time. 
	const long int res = fib(30); 
	cout << res; 
	return 0; 
}

Khi chương trình trên được biên dịch và chạy bằng GCC, nó mất 0,003 giây.

Nếu chúng ta loại bỏ từ const dòng bên dưới, thì giá trị của fib(30) không được xác định tại thời điểm biên dịch, vì kết quả của constexpr không được sử dụng trong biểu thức const.

Thay,
  const long int res = fib(30);  
Thành,
  long int res = fib(30);

Sau thay đổi trên, chương trình tốn 0.017 giây để khi thực thi.

constexpr với const

constexpr và const hướng đến các mục tiêu khác nhau. constexpr chủ yếu để tối ưu hóa trong khi const dành cho các đối tượng hằng thực tế, chẳng hạn như số Pi. Cả hai đều có thể áp dụng cho các phương thức thành viên. Các phương thức thành viên được khai báo là const để đảm bảo rằng không có thay đổi ngẫu nhiên nào của phương thức. Mặt khác, ý tưởng sử dụng constexpr là tính toán các biểu thức tại thời điểm biên dịch để có thể tiết kiệm thời gian khi thực thi. const chỉ có thể được sử dụng với hàm thành viên không tĩnh trong khi constexpr có thể được sử dụng với các hàm thành viên và không phải thành viên, ngay cả với các hàm xây dựng nhưng với điều kiện đối số và kiểu trả về phải là kiểu string.


Đã đăng vào

trong

bởi

Bình luận

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *