IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 《Effective Modern C++》学习笔记 - Item 15: 尽可能使用 constexpr -> 正文阅读

[C++知识库]《Effective Modern C++》学习笔记 - Item 15: 尽可能使用 constexpr

  • constexpr 关键字的概念丰富,作用于对象和函数时意义不同。

  • 作用于对象,constexpr 描述的对象是常量,且值在编译期已知

    int sz;								// 未初始化的int
    
    constexpr auto arraySize1 = sz;		// error! sz的值在编译期未知
    const auto arraySize2 = sz;			// ok. arraySize2是sz的const copy。MSVS过编译但链接报错,GCC可以运行且输出为0。

    std::array<int, sz> data1;			// error, std::array的size必须在编译期已知
    std::array<int, arraySize2> data2;	// error, 同上
    
    constexpr auto arraySize3 = 10;		// ok
    std::array<int, arraySize3> data3;	// ok
  • 总结:所有 constexpr 对象都是 const,但不是所有 const 对象都是 constexpr。当你需要保证一个变量是编译期已知(已初始化)的常量时,使用 constexpr 而不是 const

  • 作用于函数,constexpr 描述的函数被调用时如果参数是编译期常量,则其值也在编译期被计算;如果有一个或更多参数在编译期未知,则表现与普通函数一样。相当于是一个纯编译期的常量函数与一个普通函数的二合一。

  • 接下来通过一个情景展示 constexpr 的使用如何扩展到超出你想象的范围。假设我们要在一个 std::array 中存储某个系统的状态,状态的数量(数组空间)大小是 3 n 3^n 3n,其中 n 或许是或许不是一个常量。这里有两个原因使我们不能使用 std::pow 函数:一,它作用于浮点型;二,它不是 constexpr,所以不能将它用于 std::array 的size。那我们就自己写一个:

constexpr int pow(int base, int exp) noexcept {
    return (exp == 0 ? 1 : base * pow(base, exp - 1));
}
...
constexpr auto num = 5;
std::array<int, pow(3, 5)> results;
  • C++11对 constexpr 函数的限制是其只能有一个语句:return,可以用条件运算符 ?: 代替 if-else 和用递归来代替循环。C++14放宽了这一要求,于是可以写一个循环版本的 pow 函数:
constexpr int pow(int base, int exp) noexcept {
    auto result = 1;
    for (int i = 0; i < exp; ++i)   result *= base;
    return result;
}
  • constexpr 函数只能接受和返回字面类型(literal types),即在编译期有确定值的类型。所有内建类型除 void 均满足这一点,而实际上用户定义的类型也可以满足,因为构造和其它成员函数可以被声明为 constexpr
class Point {
public:
    constexpr Point(double xVal = 0, double yVal = 0) noexcept
        : x(xVal), y(yVal)
    {}

    constexpr double xValue() noexcept { return x; }
    constexpr double yValue() noexcept { return y; }

    constexpr void setX(double newX) noexcept { x = newX; } // C++14
    constexpr void setY(double newY) noexcept { y = newY; }

private:
    double x, y;
};
  • C++11中,两个 setter 函数不能被声明为 constexpr,因为(1)它们的返回类型是 void;(2)constexpr 隐含为 const 条件,而它们更改了数据成员的值。C++14中放宽了这两个限制,于是它们也能是 constexpr 函数了。于是,以下 Point 的构建、运算等操作都可以在编译期完成:
constexpr
Point midPoint(const Point& p1, const Point& p2) noexcept
{
    return Point((p1.xValue() + p2.xValue()) / 2,
                 (p1.yValue() + p2.yValue()) / 2);
}
constexpr
Point reflection(const Point& p) noexcept
{
    Point result;
    result.setX(-p.xValue());
    result.setY(-p.yValue());
    return result;
}

constexpr Point p1(9.4, 27.7);
constexpr Point p2(28.8, 5.3);

constexpr auto mid = midPoint(p1, p2);
constexpr auto reflectedMid = reflection(mid);

总结

  1. constexpr 对象是 const,且其值在编译期已知(必须是经过初始化的)。
  2. constexpr 函数当使用编译期已知量作为参数调用时其结果也在编译期得出。
  3. constexpr 是对象或函数声明(接口)的一部分。
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-24 18:17:43  更:2021-12-24 18:18:03 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 13:50:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码