Namespaces
Variants

const_cast conversion

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

在不同 cv 限定类型之间进行转换。

目录

语法

const_cast< 目标类型 >( 表达式 )

返回类型为 target-type 的值。

说明

只有以下转换可以通过 const_cast 实现:

1) 对于两个 相似 的对象指针或数据成员指针类型 T1 T2 ,若 T1 T2 仅因 cv 限定符不同(形式化地说,若考虑两者的 限定符分解 ,每个 P1_i P2_i 对所有 i 均相同),则类型 T1 的纯右值可转换为 T2
  • expression 是空指针值,结果也是空指针值。
  • expression 是空成员指针值,结果也是空成员指针值。
  • expression 指向某个对象,结果指向同一对象。
  • expression 指向某对象末尾之后的位置,结果指向同一对象末尾之后的位置。
  • expression 指向某个数据成员,结果指向同一数据成员。

即使 expression 是纯右值,也不会执行 临时物化

(since C++17)
2) 对于两个 对象类型 T1 T2 ,如果指向 T1 的指针可以通过 const_cast < T2 * > 显式转换为“指向 T2 的指针”类型,则还可以进行以下转换:
  • 类型为 T1 的左值可以通过 const_cast < T2 & > 显式转换为类型为 T2 的左值。
  • 类型为 T1 的泛左值可以通过 const_cast < T2 && > 显式转换为类型为 T2 的亡值。
  • 如果 T1 是类类型或数组类型,类型为 T1 的纯右值可以通过 const_cast < T2 && > 显式转换为类型为 T2 的亡值。
(C++11 起)

结果引用指向原始对象。

(C++17 前)

如果 表达式 是泛左值,则结果引用指向原始对象。否则,结果引用指向 实质化的临时对象

(C++17 起)

与所有强制转换表达式一样,结果是:

  • target-type 是左值引用类型 或函数类型的右值引用 (C++11 起) ,则为左值;
  • target-type 是对象类型的右值引用,则为 xvalue;
(since C++11)
  • 否则为纯右值。

去除 const 限定

对于两个不同的类型 T1 T2 ,从 T1 T2 的转换 会抛弃常量性 的条件是:存在 T2 限定分解 形式为“cv2_0 P2_0 cv2_1 P2_1 ... cv2_n−1 P2_n−1 cv2_n U2”,且不存在任何能将 T1 转换为“cv2_0 P1_0 cv2_1 P1_1 ... cv2_n−1 P1_n−1 cv2_n U1”(相同的 cv 限定符组件,不同的 P 组件和 U 组件)的 限定转换

如果从类型 T1* 的纯右值到类型 T2* 的转换会抛弃 const 限定,那么从类型 T1 的表达式到 T2 引用的转换同样会抛弃 const 限定。

只有 const_cast 可用于去除常量性。

“抛弃常量性”意味着“抛弃易变性”,因为限定转换同样无法抛弃易变性。

注释

指向函数的指针和指向成员函数的指针不受 const_cast 约束。

const_cast 使得可以形成指向非 const 类型的引用或指针,而该引用或指针实际上指向的是 const 对象 ;或者形成指向非 volatile 类型的引用或指针,而该引用或指针实际上指向的是 volatile 对象 。通过非 const 访问路径修改 const 对象,或通过非 volatile glvalue 引用 volatile 对象会导致未定义行为。

关键词

const_cast

示例

#include <iostream>
struct type
{
    int i;
    type(): i(3) {}
    void f(int v) const
    {
        // this->i = v;                 // 编译错误:this 是指向常量的指针
        const_cast<type*>(this)->i = v; // 只要 type 对象不是常量就可行
    }
};
int main()
{
    int i = 3;                 // i 未声明为常量
    const int& rci = i;
    const_cast<int&>(rci) = 4; // 可行:修改 i
    std::cout << "i = " << i << '\n';
    type t; // 如果这是 const type t,则 t.f(4) 将是未定义行为
    t.f(4);
    std::cout << "type::i = " << t.i << '\n';
    const int j = 3; // j 被声明为常量
    [[maybe_unused]]
    int* pj = const_cast<int*>(&j);
    // *pj = 4;      // 未定义行为
    [[maybe_unused]]
    void (type::* pmf)(int) const = &type::f; // 成员函数指针
    // const_cast<void(type::*)(int)>(pmf);   // 编译错误:const_cast 不能
                                              // 用于函数指针
}

输出:

i = 4
type::i = 4

缺陷报告

以下行为变更缺陷报告被追溯应用于先前发布的C++标准。

缺陷报告 适用范围 发布时行为 正确行为
CWG 1965 C++11 const_cast 无法将右值引用绑定到数组纯右值 允许绑定此类引用
CWG 2879 C++17 指针纯右值操作数会被实质化 不进行实质化处理

参考文献

  • C++23 标准 (ISO/IEC 14882:2024):
  • 7.6.1.11 常量转换 [expr.const.cast]
  • C++20 标准 (ISO/IEC 14882:2020):
  • 7.6.1.10 常量转换 [expr.const.cast]
  • C++17 标准 (ISO/IEC 14882:2017):
  • 8.2.11 常量转换 [expr.const.cast]
  • C++14 标准 (ISO/IEC 14882:2014):
  • 5.2.11 常量转换 [expr.const.cast]
  • C++11 标准 (ISO/IEC 14882:2011):
  • 5.2.11 常量转换 [expr.const.cast]
  • C++98 标准 (ISO/IEC 14882:1998):
  • 5.2.11 常量转换 [expr.const.cast]
  • C++03 标准 (ISO/IEC 14882:2003):
  • 5.2.11 常量转换 [expr.const.cast]

参见