const与constexpr

来源:互联网 发布:flash数据修改 编辑:程序博客网 时间:2024/06/06 03:44

const volatile mutable

  • const 定义对象为常量
  • volatile 定义对象为易变。
  • mutable
    应用于非引用非 const 类型的非静态类成员,并指定该成员不影响类的外部可见状态(常用于互斥、内存缓存、惰性求值、及访问设备)。 const 类实例的 mutable 成员是可修改的。(注意: C++ 语言文法将 mutable 当做 storage-class-specifier (存储类指定符),但它不影响存储类。)
int main(){    int n1 = 0;           // 非 const 对象    const int n2 = 0;     // const 对象    int const n3 = 0;     // const 对象(同 n2 )    volatile int n4 = 0;  // volatile 对象    const struct    {        int n1;        mutable int n2;    } x = {0, 0};      // 带 mutable 成员的 const 对象    n1 = 1; // ok ,可修改对象//  n2 = 2; // 错误:不可修改对象    n4 = 3; // ok ,当做副效应//  x.n1 = 4; // 错误: const 对象的成员为 const    x.n2 = 4; // ok , const 对象的 mutable 成员不是 const    const int& r1 = n1; // 绑定到非 const 对象的 const 引用//  r1 = 2; // 错误:试图通过到 const 的引用修改    const_cast<int&>(r1) = 2; // ok ,修改非 const 对象 n1    const int& r2 = n2; // 绑定到 const 对象的 const 引用//  r2 = 2; // 错误:试图通过到 const 的引用修改//  const_cast<int&>(r2) = 2; // 未定义行为:试图修改 const 对象 n2}

constexpr

  • constexpr
    constexpr 指定符声明可以在编译时求得函数或变量的值。然后这些变量和函数(若给定了合适的函数参数)可用于仅允许编译时常量表达式之处。用于对象的 constexpr 指定符隐含 const 。用于函数的 constexpr 指定符或 static 成员变量 (C++17 起)隐含inline。

  • constexpr变量必须满足下列要求

    • 其类型必须是字面类型(LiteralType)
    • 它必须被立即初始化
    • 其初始化的完整表达式,包括所有隐式转换、构造函数调用等,都必须是常量表达式
  • constexpr函数必须满足下列要求

    • 它必须非虚
    • 其返回类型必须是字面类型(LiteralType)
    • 其每个参数都必须是字面类型(LiteralType)
    • 至少存在一组参数值,令函数的一个调用可以为已求值的核心常量表达式的子表达式(对于构造函数,在常量初始化器中使用就够了 (C++14 起))。不要求对此行为的诊断
  • constexpr构造函数必须满足下列要求

    • 其每个参数都必须是字面类型(LiteralType).
    • 该类不能有虚基类
    • 该构造函数不可有函数try块
#include <iostream>#include <stdexcept>// C++11 constexpr函数使用递归而非迭代// (C++14 constexpr函数可使用局部变量和循环)constexpr int factorial(int n){    return n <= 1? 1 : (n * factorial(n - 1));}// 字面类class conststr {    const char* p;    std::size_t sz;public:    template<std::size_t N>    constexpr conststr(const char(&a)[N]): p(a), sz(N - 1) {}    // constexpr函数通过抛异常来提示错误    // C++11中,它们必须用条件运算符?:这么做    constexpr char operator[](std::size_t n) const    {        return n < sz? p[n] : throw std::out_of_range("");    }    constexpr std::size_t size() const { return sz; }};// C++11 constexpr函数必须把一切放在单条return语句中// (C++14无该要求)constexpr std::size_t countlower(conststr s, std::size_t n = 0,                                             std::size_t c = 0){    return n == s.size()? c :           'a' <= s[n] && s[n] <= 'z'? countlower(s, n + 1, c + 1) :                                       countlower(s, n + 1, c);}// 输出函数要求编译时常量,以测试template<int n>struct constN{    constN() { std::cout << n << '\n'; }};int main(){    std::cout << "4! = " ;    constN<factorial(4)> out1; // 在编译时计算    volatile int k = 8; // 不允许使用volatile者优化    std::cout << k << "! = " << factorial(k) << '\n'; // 运行时计算    std::cout << "the number of lowercase letters in \"Hello, world!\" is ";    constN<countlower("Hello, world!")> out2; // 隐式转换到conststr}