C++中const与constexpr区别

对于对象来说

const指的是编译期常量和运行时常量,两者并没有区分
constexpr特指编译期常量

对于函数来说

const可以修饰类的成员函数,被修饰的函数在执行期间不会改变对象的值。

class Person{
    public :
        string getName() const;
        void setAge() const;
    private :
        string name;
        mutable int age;
}

// 可以执行
string Person::getName() const
{
    return this->name;
}

// 不能执行
string Person::getName() const
{
    this->name = "test";
    return this->name;
}
    
//可以执行
void Person::setAge() const
{
    ++age;
}

假设此函数未public限定,且name数据成员没有使用mutable修饰,那么此函数在调用期间不会改变this所指的对象,也就是说,如果某个被修饰成const的成员函数在执行期间改变了this中的数据成员,那么这个函数会报错。

如果在此类函数中改变了使用mutable修饰的数据成员,这是允许的。

constexpr修饰的函数,返回值不一定是编译期常量

constexpr int foo(int i)
{
    return ++i;
}

int main()
{
    int i = 10;
    // 成功调用
    array<int, foo(5)> arr;
    // 成功调用
    foo(i);
    // 错误
    array<int, foo(i)> arr1;
    return 0;
}

上面的代码中,第一次和第二次执行都是正确的,第三次执行会报错。

  • 第一次中,foo(5)使用的是常量表达式5,所以在编译期间就可以得出结果,从而确定array的大小,所以这个声明是正确的;
  • 第二次中,foo(i)使用的是变量,在运行时可以得到结果,所以这个调用是正确的;
  • 第三次中,foo(i)使用的是变量,在运行时才能得到结果,但array的声明要求在编译期就必须要确定其大小,且不能改变,所以这个生命是错误的。
    所以,对于constexpr修饰的函数,如果其传入的参数可以在编译期算出来,那么这个函数就会产生编译期的值。如果传入的参数不能在编译时期计算出来,那么constexpr修饰的函数就和普通函数一样了。