一般情况下,if
语句的条件表达式在运行时求值。
然而,若条件为常量表达式,如下例所示,则情形有所不同:
#include <iostream>
int main()
{
constexpr double gravity{ 9.8 };
// 提示:同一类型的低精度浮点字面量可直接进行相等比较
if (gravity == 9.8) // 常量表达式,恒为真
std::cout << "Gravity is normal.\n"; // 将始终执行
else
std::cout << "We are not on Earth.\n"; // 永不执行
return 0;
}
由于 gravity
被声明为 constexpr
并以值 9.8
初始化,条件 gravity == 9.8
必然为真,于是 else
分支永远不会执行。
在运行时对一个 constexpr
条件求值是一种浪费(其结果始终不变),同样,把永远不会执行的代码也编译进可执行文件也是一种浪费。
C++17 的 constexpr if
语句
C++17 引入了 constexpr if
语句,其条件必须是常量表达式,并在编译时求值。
- 若
constexpr
条件为真,则整个if-else
结构被替换为 true-statement; - 若为假,则整个
if-else
结构被替换为 false-statement(若存在),否则替换为空。
使用 constexpr if
时,需在 if
后添加关键字 constexpr
:
#include <iostream>
int main()
{
constexpr double gravity{ 9.8 };
if constexpr (gravity == 9.8) // 使用 constexpr if
std::cout << "Gravity is normal.\n";
else
std::cout << "We are not on Earth.\n";
return 0;
}
编译上述代码时,编译器在编译期求值,发现条件恒为真,于是只保留 std::cout << "Gravity is normal.\n";
这一语句。
换句话说,编译器实际生成的代码等价于:
int main()
{
constexpr double gravity{ 9.8 };
std::cout << "Gravity is normal.\n";
return 0;
}
最佳实践
当条件为常量表达式时,优先使用 constexpr if
而非普通 if
。
现代编译器与 C++17 中的 constexpr
条件
出于优化目的,现代编译器通常会把带有 constexpr
条件的普通 if
视为 constexpr if
来处理,但并非强制要求。
若编译器遇到带 constexpr
条件的普通 if
,可能会发出警告,提示改用 if constexpr
,以确保即使关闭优化也能在编译期完成求值。