首页 > 编程语言 >Modern C++ ——constexpr的各种用法

Modern C++ ——constexpr的各种用法

时间:2023-02-10 14:23:19浏览次数:46  
标签:函数 int Modern C++ constexpr 表达式 常量

Modern C++ ——constexpr的用法

Reference

《现代C++语言核心特性解析》

为什么引入constexpr

  1. const可以定义常量,但也可以用来定义只读变量。const变量的值不一定是在编译期可以确定的,比如当通过函数返回值进行初始化时。

  2. C++标准委员会决定在C++11标准中定义一个新的关键字constexpr,它能够有效地定义常量表达式,并且达到类型安全、可移植、方便库和嵌入式系统开发的目的。

constexpr值

  1. constexpr值即常量表达式值,该值必须编译期能够确定。

  2. 常量表达式值必须被常量表达式初始化。

constexpr函数 (C++11)

(1)什么是constexpr函数?

constexpr不仅能用来定义常量表达式值,还能定义一个常量表达式函数,即constexpr函数,常量表达式函数的返回值可以在编译阶段就计算出来。

(2)C++11约束规则

1.函数必须返回一个值,所以它的返回值类型不能是void。
2.函数体必须只有一条语句:return expr,其中expr必须也是一个常量表达式。如果函数有形参,则将形参替换到expr中后,expr仍然必须是一个常量表达式。
3.函数使用之前必须有定义。
4.函数必须用constexpr声明。

(3)特殊情况

  1. 用递归完成循环,实现函数体只有单语句。
//编译失败
constexpr int sum(int x)
{
  int result = 0;
  while (x > 0)
  {
       result += x--;
  }
  return result;
}

//可改为
constexpr int sum(int x)
{
  return x > 0 ? x + sum(x - 1) : 0;
}
  1. if else双分支可以用条件表达式替代
//编译失败
constexpr int abs2(int x)
{
  if (x > 0) {
       return x;
  } else {
       return -x;
  }
}
//可改为
constexpr int sum(int x)
{
  return x > 0 ? x + sum(x - 1) : 0;
}
  1. 当带形参的常量表达式函数接受了一个非常量实参时,常量表达式函数可能会退化为普通函数。

constexpr构造函数

(1)用途

constexpr可以声明基础类型从而获得常量表达式值,除此之外constexpr还能够声明用户自定义类型。

(2)相关规则:

1.构造函数必须用constexpr声明。
2.构造函数初始化列表中必须是常量表达式。
3.构造函数的函数体必须为空(这一点基于构造函数没有返回值,所以不存在return expr)。

(3)注意

最后需要强调的是,使用constexpr声明自定义类型的变量,必须确保这个自定义类型的析构函数是平凡的(Trivial destructor),否则也是无法通过编译的。平凡析构函数必须满足下面3个条件。
1.自定义类型中不能有用户自定义的析构函数。2.析构函数不能是虚函数。3.基类和成员的析构函数必须都是平凡的。

支持浮点数

在constexpr说明符被引入之前,C++程序员经常使用enum hack来促使编译器在编译阶段计算常量表达式的值。但是因为enum只能操作整型,所以一直无法完成对于浮点类型的编译期计算。constexpr说明符则不同,它支持声明浮点类型的常量表达式值,而且标准还规定其精度必须至少和运行时的精度相同

C++14对常量表达式函数的增强

1.函数体允许声明变量,除了没有初始化、static和thread_local变量。
2.函数允许出现if和switch语句,不能使用go语句。
3.函数允许所有的循环语句,包括for、while、do-while。
4.函数可以修改生命周期和常量表达式相同的对象。
5.函数的返回值可以声明为void。
6.constexpr声明的成员函数不再具有const属性。

#include <iostream>

class X {
public:
  constexpr X() : x1(5) {}
  constexpr X(int i) : x1(0)
  {
      if (i > 0) {  
          x1 = 5;
      }
      else {
          x1 = 8;
      }
  }
  constexpr void set(int i)  // 函数的返回值可以声明为constexpr void。 可以在常量表达式函数中被调用
  {
      x1 = i;
  }
  constexpr int get() const
  {
      return x1;
  }
private:
  int x1;
};

constexpr X make_x()
{
  X x;
  x.set(42);  
  return x;
}

int main()
{
  constexpr X x1(-1);
  constexpr X x2 = make_x();
  constexpr int a1 = x1.get();
  constexpr int a2 = x2.get();
  std::cout << a1 << std::endl;
  std::cout << a2 << std::endl;
}

C++17 constexpr lambda表达式

待续。

标签:函数,int,Modern,C++,constexpr,表达式,常量
From: https://www.cnblogs.com/qiangz/p/17102606.html

相关文章

  • c++指针基础
    指针是一个变量,其存储的是值的地址,而不是值本身。如何找到常规变量的地址?只需对变量应用地址运算符(&),就可以获得它的位置;intdonuts=3;&donuts就是取donuts变量的地址。......
  • 【快速学】指针是什么?指针常量、常量指针是什么?(C++)
    0、先上总结指针是什么?指针是个数据类型,它里面存储的是个地址如inta=3;,定义了一个int类型的变量a,值为3,它在内存中的地址为&a同理,int*b=3;,定义了一个int*类型的变量b......
  • c++引用lib
    如果需要引用的是第三方的lib,没有把源码引入到工程中,则需要通过传统方式引用。1.在需要引用的项目上右键属性,在vc++目录中引用目录和引用库目录。引用目录是lib头文件的......
  • 【c&c++】结构 | 结构与函数 | C语言
                 ......
  • 【c&c++】C语言snprintf()函数用法
    一、函数原型snprintf(),为函数原型intsnprintf(char*str,size_tsize,constchar*format,...)。二、函数介绍将可变个参数(...)按照format格式化成字符串,然后将其......
  • c++17区域锁std::scoped_lock
    template<class...MutexTypes>classscoped_lock;(sincec++17)作用同时持有一个或多个Mutex的RAII机制的mutex包装器,可以一次性获取多个mutex,避免发生死锁。当......
  • 学习 C++第三天
    转义字符\?在书写连续多个问号时使用,防止他们被解析成三字母词\'用于表示字符常量\“用于表示一个字符串内部的双引号\\用于表示一个反斜杠,防止它被解释为一个转义序列......
  • C++11新特性
    C++语法movesemantics(移动语义)参考资料:这个网站的大部分资料对初学者都极其友好stanfordCS106Lmovesemanticshttps://www.youtube.com/watch?v=St0MNEU5b0o&......
  • 【八大数据排序法】堆积树排序法的图形理解和案例实现 | C++
    第二十一章堆积树排序法:::hljs-center目录第二十一章堆积树排序法●前言●认识排序1.简要介绍2.图形理解3.算法分析●二、案例实现1.案例一●总结......
  • C/C++单项选择题标准化考试系统[2023-02-09]
    C/C++单项选择题标准化考试系统[2023-02-09](C)3.17单项选择题标准化考试系统【难度系数】5级【任务描述】设计一个单项选择题的考试系统,可实现试题维护、自动组卷等......