命名空间
变体
操作

隐式转换

来自 cppreference.cn
< cpp‎ | language
 
 
C++ 语言
通用主题
流程控制
条件执行语句
if
迭代语句(循环)
for
range-for (C++11)
跳转语句
函数
函数声明
Lambda 函数表达式
inline 说明符
动态异常规范 (在 C++17* 中弃用)
noexcept 说明符 (C++11)
异常
命名空间
类型
说明符
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
存储期说明符
初始化
 
 

当在上下文中使用了某种类型 T1 的表达式,而该上下文不接受该类型,但接受其他类型 T2 时,会执行隐式转换;特别是

  • 当表达式用作调用函数的参数时,该函数声明了 T2 作为参数;
  • 当表达式用作运算符的操作数时,该运算符期望 T2
  • 当初始化 T2 类型的新对象时,包括在返回 T2 类型的函数中使用 return 语句;
  • 当表达式用在 switch 语句中时(T2 是整型);
  • 当表达式用在 if 语句或循环中时(T2bool)。

只有当存在从 T1T2 的一个无歧义的隐式转换序列时,程序才是良构的(可编译)。

如果被调用的函数或运算符有多个重载,在从 T1 到每个可用的 T2 构建隐式转换序列后,重载决议规则会决定编译哪个重载。

注意:在算术表达式中,二元运算符操作数的隐式转换目标类型由另一组规则确定:常用算术转换

目录

[编辑] 转换顺序

隐式转换序列按以下顺序组成

1) 零或一个标准转换序列
2) 零或一个用户定义转换
3) 零或一个标准转换序列(仅当使用了用户定义转换时)。

当考虑构造函数或用户定义转换函数的参数时,只允许一个标准转换序列(否则用户定义转换可能会有效地链接起来)。当从一个非类类型转换为另一个非类类型时,只允许标准转换序列。

标准转换序列按以下顺序组成

1) 来自以下集合的零或一个转换
  • 左值到右值转换,
  • 数组到指针转换,以及
  • 函数到指针转换;
2) 零或一个数值提升数值转换
3) 零或一个函数指针转换
(自 C++17 起)
4) 零或一个限定转换

用户定义转换由零或一个非显式的单参数转换构造函数或非显式的转换函数调用组成。

当且仅当 T2 可以从 e 进行复制初始化时,表达式 e 才被认为是隐式可转换为 T2 的,即声明 T2 t = e; 是良构的(可以编译),对于某些发明的临时变量 t。请注意,这与直接初始化T2 t(e))不同,在直接初始化中,还会考虑显式构造函数和转换函数。

[编辑] 语境转换

在以下上下文中,期望类型为 bool,并且如果声明 bool t(e); 是良构的(即,会考虑诸如 explicit T::operator bool() const; 这样的显式转换函数),则执行隐式转换。这样的表达式 e 被称为语境转换到 bool

  • ifwhilefor 的控制表达式;
  • 内置逻辑运算符 !&&|| 的操作数;
  • 条件运算符 ?: 的第一个操作数;
  • static_assert 声明中的谓词;
  • noexcept 说明符中的表达式;
(自 C++20 起)
(自 C++11 起)

在以下上下文中,期望一个上下文特定的类型 T,并且只有当类类型 E 的表达式 e 满足以下条件时才被允许

(在 C++14 之前)
  • 在允许的类型中,恰好有一个类型 T,使得 E 具有非显式转换函数,其返回类型是(可能带有 cv 限定的)T 或对(可能带有 cv 限定的)T 的引用,并且
  • e 可以隐式转换为 T
(自 C++14 起)

这样的表达式 e 被称为语境隐式转换到指定的类型 T请注意,即使在语境转换到 bool 时会考虑显式转换函数,但在这里不会考虑它们。(自 C++11 起)

  • delete 表达式的参数(T 是任何对象指针类型);
  • 整型常量表达式,其中使用了字面类(T 是任何整型或无作用域枚举类型,选择的用户定义转换函数必须是 constexpr);
  • switch 语句的控制表达式(T 是任何整型或枚举类型)。
#include <cassert>
 
template<typename T>
class zero_init
{
    T val;
public:
    zero_init() : val(static_cast<T>(0)) {}
    zero_init(T val) : val(val) {}
    operator T&() { return val; }
    operator T() const { return val; }
};
 
int main()
{
    zero_init<int> i;
    assert(i == 0);
 
    i = 7;
    assert(i == 7);
 
    switch (i) {}     // error until C++14 (more than one conversion function)
                      // OK since C++14 (both functions convert to the same type int)
    switch (i + 0) {} // always okay (implicit conversion)
}

[编辑] 值转换

值转换是改变表达式值类别的转换。当表达式作为运算符的操作数出现时,而该运算符期望不同值类别的表达式时,就会发生值转换

  • 每当一个泛左值作为运算符的操作数出现,而该运算符需要该操作数为纯右值时,就会应用左值到右值、数组到指针或函数到指针的标准转换,以将表达式转换为纯右值。
  • 除非另有说明,否则每当一个纯右值作为运算符的操作数出现,而该运算符期望该操作数为泛左值时,就会应用临时对象实质化转换,以将表达式转换为将亡值。
(自 C++17 起)

[编辑] 左值到右值转换

左值(在 C++11 之前)泛左值(自 C++11 起) 的任何非函数、非数组类型 T 都可以隐式转换为 右值(在 C++11 之前)纯右值(自 C++11 起)

  • 如果 T 不是类类型,则 右值(在 C++11 之前)纯右值(自 C++11 起) 的类型是 T 的 cv 非限定版本。
  • 否则,右值(在 C++11 之前)纯右值(自 C++11 起) 的类型是 T

如果程序需要从不完整类型进行左值到右值转换,则该程序是病态的。

给定泛左值引用的对象为 obj

  • 当左值到右值转换发生在 sizeof 的操作数内时,不会访问 obj 中包含的值,因为该运算符不会求值其操作数。
  • 转换的结果是 obj 中包含的值。如果 Tobj 的类型之一是有符号整数类型,而另一个是相应的无符号整数类型,则结果是 T 类型的值,其值表示与 obj 相同。
(在 C++11 之前)
  • 当左值到右值转换应用于表达式 E 时,如果满足以下条件,则不会访问 obj 中包含的值
  • 转换的结果按如下方式确定
  • 如果 T 是(可能带有 cv 限定的)std::nullptr_t,则结果是空指针常量。转换不会访问 obj,因此即使 T 是 volatile 限定的,也不会有副作用,并且泛左值可以引用联合体的非活动成员。
  • 否则,如果 T 是类类型
(在 C++17 之前)
(自 C++17 起)
  • 否则,如果 obj 包含无效的指针值,则行为是实现定义的。
  • 否则,如果 obj值表示中的位对于 obj 的类型无效,则行为是未定义的。
  • 否则,obj 被读取,并且(自 C++20 起) 结果是 obj 中包含的值。如果 Tobj 的类型之一是有符号整数类型,而另一个是相应的无符号整数类型,则结果是 T 类型的值,其值表示与 obj 相同。
(自 C++11 起)

此转换模拟了将值从内存位置读取到 CPU 寄存器的行为。

[编辑] 数组到指针转换

类型为“TN 元素数组”或“T 的未知边界数组”的左值右值可以隐式转换为类型为“指向 T 的指针”的纯右值如果数组是纯右值,则会发生临时对象实质化(自 C++17 起) 结果指针指向数组的第一个元素(详细信息请参见数组到指针退化)。

[编辑] 函数到指针转换

函数类型的左值可以隐式转换为指向该函数的纯右值指针。这不适用于非静态成员函数,因为不存在引用非静态成员函数的左值。

临时对象实质化

任何完整类型 T纯右值都可以转换为相同类型 T 的将亡值。此转换通过使用临时对象作为其结果对象来求值纯右值,从而从纯右值初始化类型 T临时对象,并生成表示该临时对象的将亡值。

如果 T 是类或类类型的数组,则它必须具有可访问且非删除的析构函数。

struct S { int m; };
int i = S().m; // member access expects glvalue as of C++17;
               // S() prvalue is converted to xvalue

临时对象实质化在以下情况下发生

请注意,当从相同类型的纯右值初始化对象时(通过直接初始化复制初始化),不会发生临时对象实质化:此类对象直接从初始化器初始化。这确保了“保证复制省略”。

(自 C++17 起)

[编辑] 整型提升

小型整型(例如 char)和无作用域枚举类型的纯右值可以转换为较大型整型(例如 int)的纯右值。特别是,算术运算符不接受小于 int 类型的参数,并且如果适用,则在左值到右值转换后自动应用整型提升。此转换始终保留值。

本节中的以下隐式转换被归类为整型提升

请注意,对于给定的源类型,整型提升的目标类型是唯一的,并且所有其他转换都不是提升。例如,重载决议选择 char -> int(提升)而不是 char -> short(转换)。

[编辑] 从整型类型提升

类型为 prvaluebool 可以转换为类型为 prvalueint,其中 false 变为 0,而 true 变为 1

对于类型为 T (除了 bool 之外) 的整型类型的 val 的 prvalue

1) 如果 val 是应用于 位域 的左值到右值转换的结果,
  • 如果 int 可以表示位域的所有值,则 val 可以转换为类型为 prvalueint
  • 否则,如果 unsigned int 可以表示位域的所有值,则 val 可以转换为 unsigned int
  • 否则,val 可以根据项目 (3) 中指定的规则进行转换。
2) 否则(val 不是从位域转换而来),
  • 如果 Tchar8_t(自 C++20 起)char16_tchar32_t(自 C++11 起)wchar_t,则 val 可以根据项目 (3) 中指定的规则进行转换;
  • 否则,如果 T整数转换等级低于 int 的等级
  • 如果 int 可以表示 T 的所有值,则 val 可以转换为类型为 prvalueint
  • 否则,val 可以转换为类型为 prvalueunsigned int
3) 在项目 (1)(不适合 unsigned int 的转换后的位域)或项目 (2)(T 是给定的字符类型之一)中指定的情况下,val 可以转换为以下类型中第一个可以表示其底层类型所有值的类型的 prvalue
  • int
  • unsigned int
  • long
  • unsigned long
  • long long
  • unsigned long long
  • T 的底层类型
(自 C++11 起)

编辑 从枚举类型提升

底层类型未固定的无作用域 枚举 类型的 prvalue 可以转换为以下列表中第一个能够容纳其整个值范围的类型的 prvalue

  • int
  • unsigned int
  • long
  • unsigned long
  • 整数转换等级高于 long long 的等级,
  • 其整数转换等级在所有扩展整数类型中是最低的,并且
  • 如果存在两个在所有扩展整数类型中具有最低整数转换等级的类型,则它是带符号的。
(自 C++11 起)


底层类型固定的无作用域枚举类型的 prvalue 可以转换为其底层类型。此外,如果底层类型也受整数提升的影响,则转换为提升后的底层类型。为了 重载解析 的目的,转换为未提升的底层类型更好。

(自 C++11 起)

编辑 浮点提升

类型为 prvalueprvalue 可以转换为类型为 double 的 prvalue。值不会改变。

此转换称为浮点提升

编辑 数值转换

与提升不同,数值转换可能会更改值,并可能丢失精度。

编辑 整型转换

整型类型或无作用域枚举类型的 prvalue 可以转换为任何其他整型类型。如果转换列在整数提升下,则它是提升而不是转换。

  • 如果目标类型是无符号类型,则结果值是等于源值的最小无符号值 2n
    ,其中 n 是用于表示目标类型的位数。
  • 也就是说,根据目标类型是更宽还是更窄,有符号整数会被符号扩展[1]或截断,而无符号整数分别会被零扩展或截断。
  • 如果目标类型是有符号类型,并且源整数可以在目标类型中表示,则值不会改变。否则,结果是 实现定义的(直到 C++20)等于源值模 2n
    的目标类型的唯一值,其中 n 是用于表示目标类型的位数
    (自 C++20 起)
    (请注意,这与 有符号整数算术溢出 不同,后者是未定义的)。
  • 如果源类型是 bool,则值 false 转换为零,值 true 转换为目标类型的值一(请注意,如果目标类型是 int,这是整数提升,而不是整数转换)。
  • 如果目标类型是 bool,则这是布尔转换(请参见下文)。
  1. 这仅在算术是二进制补码时适用,而二进制补码仅对精确宽度整数类型是必需的。但是请注意,目前所有带有 C++ 编译器的平台都使用二进制补码算术。

编辑 浮点转换

浮点类型的 prvalue 可以转换为任何其他浮点类型的 prvalue。

(直到 C++23)

浮点类型的 prvalue 可以转换为任何其他浮点类型的 prvalue,其浮点转换等级大于或等于。

标准浮点类型的 prvalue 可以转换为任何其他标准浮点类型的 prvalue。

static_cast 可用于显式地将浮点类型的 prvalue 转换为任何其他浮点类型。

(自 C++23 起)

如果转换列在浮点提升下,则它是提升而不是转换。

  • 如果源值可以在目标类型中精确表示,则它不会改变。
  • 如果源值介于目标类型的两个可表示值之间,则结果是这两个值之一(具体是哪一个由实现定义,但如果支持 IEEE 算术,则舍入默认到最接近的值)。
  • 否则,行为是未定义的。

编辑 浮点到整型转换

浮点类型的 prvalue 可以转换为任何整型类型的 prvalue。小数部分被截断,也就是说,小数部分被丢弃。

  • 如果截断后的值无法放入目标类型,则行为是未定义的(即使目标类型是无符号类型,模算术也不适用)。
  • 如果目标类型是 bool,则这是布尔转换(请参见下文)。

整型或无作用域枚举类型的 prvalue 可以转换为任何浮点类型的 prvalue。如果可能,结果是精确的。

  • 如果值可以放入目标类型但无法精确表示,则由实现定义是选择最接近的较高可表示值还是最接近的较低可表示值,但如果支持 IEEE 算术,则舍入默认到最接近的值
  • 如果值无法放入目标类型,则行为是未定义的。
  • 如果源类型是 bool,则值 false 转换为零,值 true 转换为一。

编辑 指针转换

空指针常量可以转换为任何指针类型,结果是该类型的空指针值。这种转换(称为空指针转换)允许作为单个转换转换为 cv 限定类型,也就是说,它不被视为数值转换和限定转换的组合。

指向任何(可选的 cv 限定)对象类型 Tprvalue 指针可以转换为指向(相同 cv 限定的)void 的 prvalue 指针。结果指针表示与原始指针值相同的内存位置。

  • 如果原始指针是空指针值,则结果是目标类型的空指针值。

类型为“指向(可能 cv 限定的)Derived”的 prvalue ptr 可以转换为类型为“指向(可能 cv 限定的)Base”的 prvalue,其中 BaseDerived基类,并且 Derived完整类类型。如果 Base 是不可访问的或不明确的,则程序是非良构的。

  • 如果 ptr 是空指针值,则结果也是空指针值。
  • 否则,如果 BaseDerived虚基类,并且 ptr 不指向类型相似Derived 且在其生命周期内或在其构造或析构期间的对象,则行为是未定义的。
  • 否则,结果是指向派生类对象的基类子对象的指针。

编辑 指向成员的指针转换

空指针常量可以转换为任何指向成员的指针类型,结果是该类型的空成员指针值。这种转换(称为空成员指针转换)允许作为单个转换转换为 cv 限定类型,也就是说,它不被视为数值转换和限定转换的组合。

类型为“指向类型为(可能 cv 限定的)TBase 的成员的指针”的 prvalue 可以转换为类型为“指向类型为(相同 cv 限定的)TDerived 的成员的指针”的 prvalue,其中 BaseDerived 的基类,并且 Derived 是完整类类型。如果 Base 是不可访问的、不明确的或 Derived 的虚基类,或者是 Derived 的某些中间虚基类的基类,则程序是非良构的。

  • 如果 Derived 不包含原始成员,并且不是包含原始成员的类的基类,则行为是未定义的。
  • 否则,结果指针可以使用 Derived 对象进行解引用,它将访问该 Derived 对象的 Base 基类子对象内的成员。

编辑 布尔转换

整型、浮点型、无作用域枚举、指针和指向成员的指针类型的 prvalue 可以转换为类型为 bool 的 prvalue。

零值(对于整型、浮点型和无作用域枚举)以及空指针和空成员指针值变为 false。所有其他值变为 true

直接初始化 的上下文中,bool 对象可以从类型为 std::nullptr_t 的 prvalue 初始化,包括 nullptr。结果值是 false。但是,这不被认为是隐式转换。

(自 C++11 起)

编辑 限定转换

一般来说

  • 指向cv 限定类型 T 的指针类型的 prvalue 可以转换为指向更 cv 限定的相同类型 T 的 prvalue 指针(换句话说,可以添加常量性和易变性)。
  • X 中指向 cv 限定类型 T 的成员的指针类型的 prvalue 可以转换为类 X 中指向更 cv 限定类型 T 的成员的 prvalue 指针。

“限定转换”的形式定义在下文给出。

编辑 相似类型

非正式地,如果忽略顶层 cv 限定,则两种类型是相似的

  • 它们是相同的类型;或
  • 它们都是指针,并且指向的类型是相似的;或
  • 它们都是指向同一类的成员的指针,并且指向的成员的类型是相似的;或
  • 它们都是数组,并且数组元素类型是相似的。

例如

  • const int* const *int** 是相似的;
  • int (*)(int*)int (*)(const int*) 是不相似的;
  • const int (*)(int*)int (*)(int*) 是不相似的;
  • int (*)(int* const)int (*)(int*) 是相似的(它们是相同的类型);
  • std::pair<int, int>std::pair<const int, int> 是不相似的。

形式上,类型相似性是根据限定分解定义的。

类型 T限定分解是组件 cv_iP_i 的序列,使得 T 是 “cv_0 P_0 cv_1 P_1 ... cv_n−1 P_n−1 cv_n U”,对于非负 n,其中

  • 每个 cv_i 都是 constvolatile 的集合,并且
  • 每个 P_i
  • “指向...的指针”,
  • “指向类 C_i 的类型为...的成员的指针”,
  • N_i 的数组”,或
  • “未知边界的数组”。

如果 P_i 指定一个数组,则元素类型上的 cv 限定符 cv_i+1 也被视为数组的 cv 限定符 cv_i

// T is “pointer to pointer to const int”, it has 3 qualification-decompositions:
// n = 0 -> cv_0 is empty, U is “pointer to pointer to const int”
// n = 1 -> cv_0 is empty, P_0 is “pointer to”,
//          cv_1 is empty, U is “pointer to const int”
// n = 2 -> cv_0 is empty, P_0 is “pointer to”,
//          cv_1 is empty, P_1 is “pointer to”,
//          cv_2 is “const", U is “int”
using T = const int**;
 
// substitute any of the following type to U gives one of the decompositions:
// U = U0 -> the decomposition with n = 0: U0
// U = U1 -> the decomposition with n = 1: pointer to [U1]
// U = U2 -> the decomposition with n = 2: pointer to [pointer to [const U2]]
using U2 = int;
using U1 = const U2*;
using U0 = U1*;

如果它们各自存在一个限定分解,并且两个限定分解满足以下所有条件,则两种类型 T1T2相似的

  • 它们具有相同的 n
  • U 表示的类型是相同的。
  • 对应的 P_i 组件是相同的 或者一个是“N_i 的数组”,另一个是“未知边界的数组”(自 C++20 起),对于所有 i
// the qualification-decomposition with n = 2:
// pointer to [volatile pointer to [const int]]
using T1 = const int* volatile *;
 
// the qualification-decomposition with n = 2:
// const pointer to [pointer to [int]]
using T2 = int** const;
 
// For the two qualification-decompositions above
// although cv_0, cv_1 and cv_2 are all different,
// they have the same n, U, P_0 and P_1,
// therefore types T1 and T2 are similar.

编辑 组合 cv 限定符

在下面的描述中,类型 Tn 的最长限定分解表示为 Dn,其组件表示为 cvn_iPn_i

如果满足以下所有条件,则类型 T1 的 prvalue 表达式可以转换为类型 T2

  • T1T2 是相似的。
  • 对于每个非零 i,如果 constcv1_i 中,则 const 也在 cv2_i 中,对于 volatile 也是如此。
  • 对于每个非零 i,如果 cv1_icv2_i 不同,则 const 在每个 k[1i) 中的 cv2_k 中。

类型 T1T2限定组合类型是类似于 T1 的类型 T3,使得

  • cv3_0 为空,
  • 对于每个非零 icv3_icv1_icv2_i 的并集,并且
  • 如果 cv3_icv1_ic2_i 不同,则将 const 添加到每个 k[1i) 中的 cv3_k
(直到 C++20)

类型 T1T2限定组合类型是类似于 T1 的类型 T3,其中 D3 满足以下所有条件

  • cv3_0 为空。
  • 对于每个非零 icv3_icv1_icv2_i 的并集。
  • 如果 P1_iP2_i 是“未知边界的数组”,则 P3_i 是“未知边界的数组”,否则它是 P1_i
  • 如果 cv3_icv1_icv2_i 不同,或者 P3_iP1_iP2_i 不同,则将 const 添加到每个 k[1i) 中的 cv3_k

如果 T1T2 的限定组合类型是 cv 非限定的 T2,则类型 T1 的 prvalue 可以转换为类型 T2

(自 C++20 起)
// longest qualification-decomposition of T1 (n = 2):
// pointer to [pointer to [char]]
using T1 = char**;
 
// longest qualification-decomposition of T2 (n = 2):
// pointer to [pointer to [const char]]
using T2 = const char**;
 
// Determining the cv3_i and T_i components of D3 (n = 2):
// cv3_1 = empty (union of empty cv1_1 and empty cv2_1)
// cv3_2 = “const” (union of empty cv1_2 and “const” cv2_2)
// P3_0 = “pointer to” (no array of unknown bound, use P1_0)
// P3_1 = “pointer to” (no array of unknown bound, use P1_1)
// All components except cv_2 are the same, cv3_2 is different from cv1_2,
// therefore add “const” to cv3_k for each k in [1, 2): cv3_1 becomes “const”.
// T3 is “pointer to const pointer to const char”, i.e., const char* const *.
using T3 = /* the qualification-combined type of T1 and T2 */;
 
int main()
{
    const char c = 'c';
    char* pc;
    T1 ppc = &pc;
    T2 pcc = ppc; // Error: T3 is not the same as cv-unqualified T2,
                  //        no implicit conversion.
 
    *pcc = &c;
    *pc = 'C';    // If the erroneous assignment above is allowed,
                  // the const object “c” may be modified.
}

请注意,在 C 编程语言中,const/volatile 只能添加到第一级

char** p = 0;
char * const* p1 = p;       // OK in C and C++
const char* const * p2 = p; // error in C, OK in C++

函数指针转换

  • 指向非抛出函数的指针类型的 prvalue 可以转换为指向可能抛出函数的指针类型的 prvalue。
  • 指向非抛出成员函数的指针类型的 prvalue 可以转换为指向可能抛出成员函数的指针类型的 prvalue。
void (*p)();
void (**pp)() noexcept = &p; // error: cannot convert to pointer to noexcept function
 
struct S
{
    typedef void (*p)();
    operator p();
};
void (*q)() noexcept = S(); // error: cannot convert to pointer to noexcept function
(自 C++17 起)

编辑 安全 bool 问题

在 C++11 之前,设计一个应在布尔上下文(例如 if (obj) { ... })中使用的类存在一个问题:给定一个用户定义的转换函数,例如 T::operator bool() const;,隐式转换序列允许在该函数调用之后再进行一次标准转换序列,这意味着生成的 bool 可以转换为 int,从而允许诸如 obj << 1;int i = obj; 之类的代码。

std::basic_ios 中可以看到此问题的早期解决方案,它最初定义了 operator void*,以便诸如 if (std::cin) {...} 之类的代码可以编译,因为 void* 可转换为 bool,但是 int n = std::cout; 不会编译,因为 void* 不可转换为 int。但这仍然允许诸如 delete std::cout; 之类的无意义代码编译。

许多 C++11 之前的第三方库都采用了一种更精细的解决方案,称为安全 Bool 惯用法std::basic_ios 也通过 LWG 问题 468 允许了这种惯用法,并且 operator void* 被替换了(请参见 注释)。

自 C++11 起,显式 bool 转换 也可用于解决安全 bool 问题。

编辑 缺陷报告

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

DR 应用于 已发布行为 正确行为
CWG 170 C++98 指向成员的指针转换的行为不明确
如果派生类没有原始成员
明确化
CWG 172 C++98 枚举类型基于其底层类型提升 改为基于其值范围
CWG 330
N4261
C++98 double* const (*p)[3] 的转换
double const * const (*p)[3] 无效
使其有效
CWG 519 C++98 空指针值不能保证
在转换为另一种指针类型时被保留
始终保留
CWG 616 C++98 从左值到右值的转换行为,对于
任何未初始化的对象和指针对象
的无效值始终是未定义的
允许不确定的 unsigned char
无效指针的使用
是实现定义的
CWG 685 C++98 枚举类型的底层类型
如果它是固定的,则在整数提升中不优先
优先考虑
CWG 707 C++98 整数到浮点转换
在所有情况下都具有定义的行为
如果
要转换的值
超出目标范围,则行为未定义
CWG 1423 C++11 std::nullptr_t 可转换为 bool
在直接初始化和复制初始化中
仅限直接初始化
CWG 1773 C++11 出现在潜在求值表达式中的名称表达式
以至于命名的对象未被 odr 使用,可能
仍在左值到右值的转换期间被求值
不求值
CWG 1781 C++11 std::nullptr_tbool 被认为是隐式
转换,即使它仅对直接初始化有效
不再被认为是
隐式转换
CWG 1787 C++98 从寄存器中缓存的不确定的
unsigned char 读取的行为是未定义的
使其良好定义
CWG 1981 C++11 上下文转换被认为是显式转换函数 不被认为是
CWG 2140 C++11 不清楚是否从
std::nullptr_t 左值进行左值到右值的转换会从内存中获取这些左值
不获取
CWG 2310 C++98 对于派生类到基类的指针转换和
基类到派生类指向成员的指针转换,
派生类类型可能是不完整的
必须是完整的
CWG 2484 C++20 char8_tchar16_t 具有不同的整数
提升策略,但它们可以适用于两者
char8_t 应该被提升
以与 char16_t 相同的方式
CWG 2485 C++98 涉及位域的整数提升没有被很好地规范 改进了规范
CWG 2813 C++23 当显式的
类纯右值的对象成员函数被调用时,临时对象实体化将会发生
将不会发生
在这种情况下
CWG 2861 C++98 一个指向类型不可访问对象的指针可以被
转换为指向基类子对象的指针
行为是
在这种情况下是未定义的
CWG 2879 C++17 临时对象实体化转换被应用于纯右值
作为期望泛左值的运算符的操作数
在某些情况下不应用
CWG 2899 C++98 左值到右值的转换可以应用于左值
指定具有无效值表示的对象
行为是
在这种情况下是未定义的
CWG 2901 C++98 从一个 unsigned int 类型的左值到右值的转换结果
引用一个值为 -1int 对象的左值是不明确的
明确化

[编辑] 参见

C 文档 关于 隐式转换