EMCPP条款15:只要有可能使用constexpr,就使用它
表面上看,constexpr
表示的是这样的值:它不仅是 const
, 而且在编译阶段就已知。关千 constexpr
函数的结果,你既不能断定它是 const
, 也不能假定其值在编译阶段就已知。
请注意,const
并未提供和 constexpr
同样的保证,因为 const
对象不一定经由编译期已知值来初始化。一言以蔽之,所有 constexpr
对象都是 const
对象,而并非所有的 const
对象都是 constexpr
对象。如果你想让编译器提供保证,让变量拥有一个值,用于要求编译期常量的语境,那么能达到这个目的的工具是 constexpr
, 而非 const
。
而 constexpr
对象的使用场景中如果涉及 constexpr
函数,正确的理解方式是以下这样:
constexpr
函数可以用在要求编译期常量的语境中。在这样的语境中,若你传给一个constexpr
函数的实参值是在编译期已知的,则结果也会在编译期间计算出来。如果任何一个实参值在编译期未知,则你的代码将无法通过编译。- 在调用
constexpr
函数时,若传入的值有一个或多个在编译期未知,则它的运作方式和普通函数无异,亦即它也是在运行期执行结果的计算。这意味着,如果函数执行的是同样的操作,仅仅应用的语境一个是要求编译期常量的,一个是用于所有其他值的话,那就不必写两个函数。constexpr
函数就可以同时满足所有需求。
constexpr
函数仅限于传入和返回字面型别 ( literal type) ,意思就是这样的型别能够持有编译期可以决议的值。在 C++11 中,所有的内建型别,除了 void
,都符合这个条件(C++14 中这个限制解除了)。但是用户自定义型别同样可能也是字面型别,因为它的构造函数和其他成员函数可能也是 constexpr
函数(C++14)。
1 | class Point { |
通常来说,
constexpr
函数里是不允许有 I/O 语句的。
要点速记
constexpr
对象都具各const
属性,并由编译期已知的值完成初始化。constexpr
函数在调用时若传入的实参值是编译期已知的,则会产出编译期结果。- 比起非
constexpr
对象或constexpr
函数而言,constexpr
对象或是constexpr
函数可以用在一个作用域更广的语境中。