const与constexpr

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(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 
#include 

// 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! = " ;
    constN4)> out1; // 在编译时计算

    volatile int k = 8; // 不允许使用volatile者优化
    std::cout << k << "! = " << factorial(k) << '\n'; // 运行时计算

    std::cout << "the number of lowercase letters in \"Hello, world!\" is ";
    constN"Hello, world!")> out2; // 隐式转换到conststr
}

你可能感兴趣的:(C++)