目录

cv-qualifier

cv-qualifier-seq

词法上,C++ 标准用 BNF 产生式描述了 cv-qualifier-seq 的词法 :TODO: §9.3/5

cv-qualifier-seq:
    cv-qualifier cv-qualifier-seq_opt

cv-qualifier:
    const
    volatile

BNF 产生式在词法上简洁明了精确,但若用自然语言表述即:cv 限定符序列是一个非空的 cv 限定符的序列,而一个 cv 限定符要么是 const 要么是 qulified 。

语法上,C++ 标准规定了每个 cv-qualifier 在一个 cv-qualifier-seq 中至多出现一次。TODO: §9.2.8.1/1

cv-qualifier

const

const 对象

一个对象若被声明为 const :

  • 它的非 mutable 子对象也是 const 的。
    • const 是子对象传播的,mutable 可以打断子对象传播。
  • 直接修改对象的表达式不合法。
    • S = ? 是直接修改对象,S.x = ? 不是直接修改对象,这里的 . 表示在修改子对象。

const 在类中的可观察影响

一个类如果包含 const 限定的非类类型静态数据成员,默认拷贝/移动赋值运算符被隐式删除。

volatile

特性比较多,核心作用归纳起来就是,volatile 限定用于处理程序无法预测的行为,并限制编译器优化。

典型的比如硬件信号是一种程序自身无法预测的行为,一个信号量如果不 volatile 限定,可能被编译器省略、合并,或者交换另一个信号量的位置。如果真的这么做了结果是比较灾难性的,硬件完全无法和程序正常沟通,C++ 通常用 volatile 处理信号量这种比较基础的硬件和程序间的交互依赖。

cv-qualified

cv-qualified 顾名思义上即被被 cv-qualifier 限定。

cv-qualified type

cv-qualified type 指被 const-qualified、volatile-qualified、const volatile-qualified 的 type 。cv-unqualified 即未被 cv-qualifed 。

每一个 cv-unqualifed 的对象类型和 void 类型,都有三个对应的 cv-qualified 版本。这四种类型变体是不同类型,它们会影响重载协议,但具有相同的二进制表示和对齐要求。

除数组外,其他的复合类型不因其组成类型的 cv-qualifier 而被 cv-qualified 。一个数组的元素是 cv-qualified 的,则该数组类型被认为是相同的 cv-qualfiled 的。[1]§6.8.3/3

函数类型永远不会被 cv-qualified 。[1]§7.3.5/5

  • cv 限定符可以出现在非静态成员函数上。实际上限定的是该函数内的纯右值 this 。

cv-qualified 的引用是不合法的,除非引用的 cv-qualifier 是被 typedef-name 或 decltype-specifier 引入的,但此时的 cv-qualifier 实际上会被忽略。[1]§9.3.3.2/1

cv-qualified 的偏序

cv-unqualified < 单 cv-qualified ,单 cv-qualified < 双 cv-qualified 。

对于单层指针,类型为“指向 cv_1 T 的指针”的纯右值可以转换为类型“指向 cv_2 T 的指针”的纯右值,如果“cv_2 T”比“cv_1 T”更 cv 限定。

对于多层指针,限定转换则需要参考限定转换的严格要求。

longest cv-decomposition

类型 T 的一个最长 cv 分解是一个由 cv_i 和 P_i 组成的序列,使得 T 是 cv_0 P_0 cv_1 P_1 \cdots cv_{n - 1} P_{n = 1} cv_n U ,其中:

  • \(n \geq 0\) 且最长;
  • cv_i 是一组 cv-qualifiers ;
  • P_i 是
    • pointer to:指针构造——把后续类型作为被指向类型,构造出指针类型。
    • pointer to member of class C_i of type:指向类 C_i 的成员指针构造——把后续类型作为该成员的类型,构造成员指针类型。
    • arrary of N_i:数组构造——把后续类型作为元素类型,构造出 N_i 个元素的数组类型。
    • arrary of unknow bound of:未知边界数组构造——把后续类型作为元素类型,构造出未知边界的元素个数的数组类型。
  • U 是剥离所有 P_i 后的最内层/底层类型。

top-level cv-qualifiers

一个 T 的最长 cv 分解若是 cv_0 P_0 cv_1 P_1 \cdots cv_{n - 1} P_{n = 1} cv_n U ,则它的顶层 cv 限定符是 cv_0 。

顶层 cv 限定符描述的是对象自身的限定,引用和函数没有顶层 cv 限定符。

这里关于 const 限定有一个常见的例子,在一个 pointer to 表达式中,如果存在 const 限定:

  • 顶层 const 限定的是对象本身,对象不可通过表达式修改。
  • 非顶层 const 限定的是 pointer to 本身,pointer to 不可通过表达式修改。

cv-qualification signature

一个 T 的最长 cv 分解若是 cv_0 P_0 cv_1 P_1 \cdots cv_{n - 1} P_{n = 1} cv_n U ,则它的 cv 限定签名是 cv_1, cv_2, \cdots, cv_n 。

similar types

两个类型 T_1 和 T_2 是相似类型,若它们的最长 cv 分解长度一样且对应 P_i 和 U 相同。

qualification conversion

类型 T_1 的纯右值可以转换为类型 T_2 ,若满足:

  • cv_{ij} 为类型 T_j 的 cv 限定签名中的 cv-qualifier 。
  • T_1 和 T_2 是相似类型。
  • \(cv_{i1} \neq cv_{i2} \Rightarrow \forall 0 < k < i. \text{const} \in cv_{k2}\) 。

[1] ISO/IEC. Working Draft, Standard for Programming Language C++: N4861[EB/OL]. (2020-04-01)[2026-09-22]. https://timsong-cpp.github.io/cppwp/n4861/. ↩

posted @ 2026-10-03 21:41  03Goose  阅读(2)  评论(0)    收藏  举报