Giải trình
Một số trình biên dịch (đặc biệt là GCC) sử dụng độ chính xác cao hơn khi đánh giá các biểu thức tại thời điểm biên dịch. Nếu một biểu thức chỉ phụ thuộc vào các đầu vào không đổi và các ký tự, nó có thể được đánh giá tại thời điểm biên dịch ngay cả khi biểu thức không được gán cho một biến constexpr. Điều này có xảy ra hay không phụ thuộc vào:
- Sự phức tạp của biểu thức
- Ngưỡng mà trình biên dịch sử dụng làm ngưỡng khi cố gắng thực hiện đánh giá thời gian biên dịch
- Các phương pháp heuristics khác được sử dụng trong các trường hợp đặc biệt (chẳng hạn như khi clang trôi qua các vòng lặp)
Nếu một biểu thức được cung cấp rõ ràng, như trong trường hợp đầu tiên, nó có độ phức tạp thấp hơn và trình biên dịch có khả năng đánh giá nó tại thời điểm biên dịch.
Tương tự, nếu một hàm được đánh dấu nội tuyến, trình biên dịch có nhiều khả năng đánh giá nó tại thời điểm biên dịch vì các hàm nội tuyến nâng cao ngưỡng mà tại đó đánh giá có thể xảy ra.
Mức tối ưu hóa cao hơn cũng làm tăng ngưỡng này, như trong ví dụ -Ofast, trong đó tất cả các biểu thức đánh giá là true trên gcc do đánh giá thời gian biên dịch chính xác cao hơn.
Chúng ta có thể quan sát hành vi này ở đây trên trình khám phá trình biên dịch. Khi được biên dịch với -O1, chỉ hàm được đánh dấu nội tuyến mới được đánh giá tại thời điểm biên dịch, nhưng tại -O3, cả hai hàm đều được đánh giá tại thời điểm biên dịch.
NB: Trong các ví dụ về trình biên dịch, tôi sử dụng printfiostream thay vì nó làm giảm độ phức tạp của hàm chính, làm cho hiệu ứng rõ ràng hơn.
Chứng minh rằng điều inlineđó không ảnh hưởng đến đánh giá thời gian chạy
Chúng tôi có thể đảm bảo rằng không có biểu thức nào được đánh giá tại thời điểm biên dịch bằng cách lấy giá trị từ đầu vào chuẩn và khi chúng tôi làm điều này, cả 3 biểu thức đều trả về false như được minh họa tại đây: https://ideone.com/QZbv6X
#include <cmath>
#include <iostream>
bool is_cube(double r)
{
return floor(cbrt(r)) == cbrt(r);
}
bool inline is_cube_inline(double r)
{
return floor(cbrt(r)) == cbrt(r);
}
int main()
{
double value;
std::cin >> value;
std::cout << (floor(cbrt(value)) == cbrt(value)) << std::endl;
std::cout << (is_cube(value)) << std::endl;
std::cout << (is_cube_inline(value)) << std::endl;
}
Ngược lại với ví dụ này , trong đó chúng tôi sử dụng cài đặt trình biên dịch giống nhau nhưng cung cấp giá trị tại thời điểm biên dịch, dẫn đến đánh giá thời gian biên dịch có độ chính xác cao hơn.