C++:常量表达式

C++11开始constexpr作为一种声明,为编译器提供了在编译期间确认结果的优化建议,满足部分编译期特性的需求

constexpr和const区别

int b=10;
const int a=b;
//运行成功
constexpr int c=b;
//编译器报错,b的值在编译期间不能确定
const int size1(){return 100;}
constexpr int size2(){return 100;}
char buf1[size1()];//报错
char buf2[size2()];//通过

constexpr修饰的变量它的值必须在编译阶段可以确认,const只是作为常类型。

对constexpr修饰的函数的约束(C++11)

  • 函数必须有一个返回值即返回值类型不能是void
  • 函数体内只能有一行用于输出返回值且返回值必须是常量表达式
  • 函数必须定义且必须用constexpr声明

注意:即使定义了一个常量表达式函数,如果形参不是常量表达式的话函数会退化为普通函数

字面类型(常量表达式中所有类型必须是字面类型)

  • 构造函数用constexpr声明
  • 构造函数初始化参数列表里是常量表达式
  • 构造函数的函数体为空
  • 基本数据类型、指针、引用、各种字面量都是字面类型

C++ 14标准规则:

  • 函数体允许声明初始化过的变量,除了static和thread_local变量
  • constexpr不在具有const属性
  • 开始支持部分代码如:if,switch,各种循环
  • 可以修改字面类型数据
  • 返回值可以是void了

C++17开始lamada表达式可以用constexpr声明时会进行隐式声明

char *buf[[](){return 1024;};];

C++17 提出了if constexpr,它可以根据一个常量表达式的返回结果有选择的编译部分代码,可以简化模板的编写,比如:特化的实现

template <typename T>
void printSize(T value) {
    if constexpr (std::is_integral<T>::value) {
        std::cout << "Size of integral type: " << sizeof(T) << " bytes" << std::endl;
    } else if constexpr (std::is_floating_point<T>::value) {
        std::cout << "Size of floating-point type: " << sizeof(T) << " bytes" << std::endl;
    } else {
        std::cout << "Size of other type: " << sizeof(T) << " bytes" << std::endl;
    }
}

C++20 标准

  • 支持constexpr虚函数
  • 运行在constexpr中进行一些默认初始化
  • 支持try catch和typeid,dynamic_cast等运算符的使用

constexpr相关关键字

  • consteval关键字,强制编译期出结果,得不到结果程序结束(C++ 20)
  • constinit关键字,用于具有静态存储持续时间的(生命周期全局)变量声明上,他要求变量具有常量初始化程序(编译阶段初始化),某种程度上可以提高程序效率

应用:
封装static_assert的参数,STL中sort源码中快排部分判断比较器是否有效时,将比较对象的顺序调换看比较结果是否是否不同,所以使用sort时比较器必须是常量表达式函数
在这里插入图片描述

STL中sort的源码中插入排序部分就用到了常量表达式用于判断迭代器的种类,如果是线性迭代器使用memmove直接移动数据,否则就需要使用循环一个一个的移动对象,这里不详细的说明了,有时间的化会写一篇博客讲一下sort源码
在这里插入图片描述
在这里插入图片描述

  • 15
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++11 引入了 constexpr 关键字,用于指定函数或对象是常量表达式常量表达式是在编译时就能计算出结果的表达式,它可以用于数组大小、模板参数等需要在编译时确定的地方。 constexpr 函数 constexpr 函数是指能在编译时求值的函数,它的返回值可以作为常量表达式使用。constexpr 函数的参数和返回值必须是字面类型。 例如,下面的函数就是一个 constexpr 函数: ```cpp constexpr int square(int x) { return x * x; } ``` 我们可以在编译时计算出 square(5) 的值,因此它是一个常量表达式。 constexpr 对象 constexpr 对象是指在编译时就能计算出值的对象。constexpr 对象必须被声明为 const,而且必须用常量表达式初始化。 例如,下面的语句定义了一个 constexpr 对象: ```cpp constexpr int max_num = 100; ``` 我们可以在编译时就知道 max_num 的值是 100,因此它是一个常量表达式。 constexpr 函数和常量表达式的限制 constexpr 函数和常量表达式有一些限制: 1. constexpr 函数必须有一个返回值,而且返回值必须是字面类型。 2. constexpr 函数的函数体必须足够简单,能在编译时被求值。 3. constexpr 函数不能包含任何副作用,比如修改全局变量或调用非 constexpr 函数。 4. constexpr 函数的参数和返回值必须是字面类型。 5. constexpr 对象必须被声明为 const,而且必须用常量表达式初始化。 6. constexpr 对象的类型必须是字面类型。 总结 constexpr 关键字用于指定函数或对象是常量表达式。constexpr 函数和常量表达式必须在编译时就能计算出值,它们有一些限制。constexpr 函数和常量表达式可以用于数组大小、模板参数等需要在编译时确定的地方。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值