const 变量
const
修饰变量,表示这个变量是不可修改,const
变量必须初始化,一经初始化就不可修改:
- 编译时初始化。
- 运行时初始化。
在编译时,可以使用编译时常量来初始化const
变量:
那么,由于SIZE
的值是在编译时就已经确定的,编译器会使用常量 100 来替代程序中出现的SIZE
。
另一方面,const
变量也可以运行时才初始化:
constexpr 变量
const
变量的值可以在编译时或运行时确定,与const
相比,constexpr
的限制更多,因为constexpr
变量的值必须在编译时就能确定。
在一些场合之下,变量的值要求是编译期就必须确定的,constexpr
变量正好满足要求:
- 数组的大小必须是编译期常量。
std::array
的大小必须是编译期常量。std::bitset
的大小必须是编译期常量。
|
|
constexpr 函数
constexpr
函数则与编译期计算有关,要是constexpr
函数所使用的变量其值能够在编译时就确定,那么constexpr
函数就能在编译时执行计算。另一方面,要是constexpr
函数所使用的变量其值只能在运行时确定,那么constexpr
就和一般的函数没区别。
C++11 要求constexpr
函数不能多于一条语句,但是碰到 if-else 语句时,但可以巧妙地使用条件操作符来替代:
C++14 中则放松了这个要求:
要是我们传递一个编译时常量给fib()
,那么fib()
在程序编译的时候就已经执行好了。代价是增加编译时间,但程序能执行得更高效。
但是,定义constexpr
变量的时候,变量的类型只能是基本数据类型、指针和引用,而不能是其它类型。
但是,我们自己定义的类型却没有这个限制,因为 constructor 和成员函数可以是constexpr
函数:
要是我们使用编译期常量来初始化Point
对象,那么,在编译的时候编译器就已经创建了这个对象:
另一方面,注意到成员函数也可以是constexpr
的,也就是说:
要是pt1
和pt2
是constexpr
变量,那么,addTwoPoint()
这个函数会在编译时就执行。
在 C++11 中,constexpr
函数隐式地是const
函数,所以你会发现set_x()
和set_y()
这两个函数不能是constexpr
函数。
但在 C++14 中,这个限制放宽了,也就是说这两个函数可以声明为constexpr
函数:
这就是说,要是Point
对象是constexpr
的,甚至在编译时可以修改它的数据成员: