c++中const与constexpr关键字

const变量的初始化时刻

const修饰变量,表示这个变量是不可修改的,因此const变量必须初始化,一经初始化就不可修改。

  1. 如果const变量的初始化值是在编译时就可以确定,则在编译时初始化;

  2. 如果const变量的初始化值是在运行时才确定,则在运行时初始化;

const int SIZE = 100;

由于SIZE的值是在编译时就已经确定的,编译器会使用常量 100 来替代程序中出现的SIZE。

vector<int> v;
const int i = v.size();

运行时初始化。

constexpr

constexpr函数的编译期计算

constexpr函数则与编译期计算有关,要是constexpr函数所使用的变量其值能够在编译时就确定,那么constexpr函数就能在编译时执行计算。另一方面,要是constexpr函数所使用的变量其值只能在运行时确定,那么constexpr就和一般的函数没区别。

C++11 要求constexpr函数不能多于一条语句,但是碰到 if-else 语句时,但可以巧妙地使用条件操作符来替代:

constexpr unsigned long long fib( unsigned n ) noexcept
{
    return ( n == 0 || n == 1 ? n : fib( n - 1 ) + fib( n - 2 ) );
}

C++14 中则放松了这个要求:

constexpr unsigned long long fib( unsigned n ) noexcept
{
    if( n == 0 || n == 1 )
    {
        return n;
    }
    else
    {
        return fib( n - 1 ) + fib( n - 2 );   
    }
}

要是我们传递一个编译时常量给fib(),那么fib()在程序编译的时候就已经执行好了。代价是增加编译时间,但程序能执行得更高效。

constexpr变量

const变量的值可以在编译时或运行时确定,与const相比,constexpr的限制更多,因为constexpr变量的值必须在编译时就能确定

在一些场合之下,变量的值要求是编译期就必须确定的,constexpr变量正好满足要求。比如数组的大小、std::array的大小、std::bitset的大小等。

constexpr auto SIZE = 100;
std::array<int, SIZE> arr;

定义constexpr变量的时候,变量的类型只能是基本数据类型、指针和引用,而不能是其它标准库类型。

// error: constexpr variable cannot have non-literal type
constexpr string str = "hello";

不过,对于我们自己定义的类型没有这个限制,因为 constructor 和成员函数可以是constexpr函数:

class Point
{
public:
    constexpr Point( double x = 0, double y = 0 )
        : x_( x ), y_( y )
    {  }
    
    constexpr double x() const noexcept {  return x_;  }
    constexpr double y() const noexcept {  return y_;  }
    void set_x( double x ) noexcept {  x_ = x;  }
    void set_y( double y ) noexcept {  y_ = y;  }
private:
    double x_, y_;
};

要是我们使用编译期常量来初始化Point对象,那么,在编译的时候编译器就已经创建了这个对象:

constexpr Point pt( 10, 20 );     // Evaluate at compiling time

在 C++11 中,constexpr函数隐式地是const函数,所以你会发现set_x()和set_y()这两个函数不能是constexpr函数。

但在 C++14 中,这个限制放宽了,也就是说这两个函数可以声明为constexpr函数:

class Point
{
public:
    // ...
    constexpr void set_x( double x ) noexcept {  x_ = x;  }
    constexpr void set_y( double y ) noexcept {  y_ = y;  }
    // ...
};

 

 

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值