首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Implicit conversions

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

  • 时,将表达式用作参数时,调用T2作为参数;
  • 当表达式作为操作数使用时,该运算符需要T2
  • 初始化类型的新对象时T2,包括return函数中返回的语句。T2
  • 当表达式在switch报表%28T2是积分型%29;
  • 当表达式在if语句或循环%28T2bool29%。

只有当存在一个明确的程序时,程序才会编译%29。隐式转换序列T1T2...

如果调用的函数或运算符有多个重载,则在构建隐式转换序列之后T1每个可用的T2,,,过载分辨率规则决定编译哪个重载。

转换顺序

隐式转换序列按以下顺序包括:

1%29 0或1标准转换序列

2%29 0或1用户定义转换

3%29 0或1标准转换序列...

当考虑构造函数或用户定义转换函数的参数时,只允许%28标准转换序列,否则用户定义的转换可以有效地链接%29。当从一个内置类型转换到另一个内置类型时,只允许一个标准转换序列。

标准转换序列按以下顺序包括:

1%29 0或1洛值转化

2%29 0或1数值推广数值转换

3) zero or one function pointer conversion;

(since C++17)

4%29 0或1资格调整...

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

表达e据说是隐式可兑换为T2当且仅当T2可以拷贝初始化从e,这就是声明T2 t = e;格式良好的%28可以编译%29,对于某些人来说是临时的。t请注意,这与直接初始化%28T2 t(e)%29,其中还将考虑显式构造函数和转换函数。

语境转换

In the following five contexts, the type bool is expected and the implicit conversion sequence is built if the declaration bool t(e); is well-formed. that is, the explicit user-defined conversion function such as explicit T::operator bool() const; is considered. Such expression e is said to be contextually convertible to bool. controlling expression of if, while, for; the logical operators !, && and ||; the conditional operator ?:; static_assert; noexcept.

(since C++11)

  • 控制表达if,,,while,,,for
  • 逻辑运算符!,,,&&||
  • 条件算子?:
  • static_assert
  • noexcept...

%28自C++11%29

在以下上下文中,特定于上下文的类型T是预期的,而表达式e类类型E只有在下列情况下才允许E有一个非显式的用户定义的转换函数对于允许的类型%28,直到C++14%29,只有一种类型T在允许的类型中,例如E具有非显式转换函数,其返回类型为%28,可能是cv限定%29。T或引用%28可能是cv-限定%29T,和e隐式可转换为T%28自C++14%29。这种表达e据说是上下文隐式转换到指定类型T请注意,显式转换函数不被考虑,即使在上下文转换到bool时也考虑了它们。%28自C++11%29。

  • 争论删除-表达式%28T是任何对象指针类型%29;
  • 积分常数表达式,其中使用文本类%28T是任何整数或非作用域枚举类型,则所选用户定义的转换函数必须为司法官29%;
  • 控件的控制表达式开关报表%28T是任何整数或枚举类型%29。

二次

代码语言:javascript
复制
#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)
}

二次

价值转换

值转换是更改价值范畴一种表达方式。每当表达式作为操作符的操作数出现时,就会发生这些操作数,该运算符期望一个不同值类别的表达式。

L值到r值转换

阿极值任何非函数、非数组类型的T可以隐式转换为prvalue同类型的。如果T是非类类型,此转换也会删除cv-限定符.。如果glvalue具有以下类型std::nullptr_t,结果的prvalue是空指针常量。nullptr...

除非在未评估上下文%28在一个大的操作数中,type id,no,或解密类型%29中,这个转换有效地复制了一个临时的类型对象。T使用原始的glvalue作为构造函数参数,该临时对象作为prvalue返回。

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

如果glvalue引用的对象包含不确定值%28,则由默认初始化一个非类自动变量%29,其行为是未定...

except if the indeterminate value is of possibly cv-qualified unsigned character type which was not cached in a CPU register, or, formally: its storage duration was static or thread-local; or a pointer to it was constructed; or it was bound to a reference. The behavior is also implementation-defined (rather than undefined) if the glvalue contains a pointer value that was invalidated by delete.

(since C++11)

  • 其存储时间是静态的或线程局部的;
  • 或者一个指向它的指针被构造;
  • 或者是和参考资料有关。

如果glvalue包含一个指针值,则此行为也是实现定义的%28,而不是未定义的%29。删除...

%28自C++11%29

数组到指针转换

安洛值或r值的“数组”NT“或”数组的未知界限T“可以隐式转换为prvalue“类型”指针指向T“.如果数组是一个prvalue,临时物化会发生。%28,因为C++17%29,由此产生的指针引用数组%28的第一个元素(参见数组到指针衰减详情见%29。

Temporary materialization A prvalue of any complete type T can be converted to an xvalue of the same type T. This conversion initializes a temporary object of type T from the prvalue by evaluating the prvalue with the temporary object as its result object, and produces an xvalue denoting the temporary object. If T is a class or array of class type, it must have an accessible and non-deleted destructor. struct X { int n; }; int k = X().n; // member access expects glvalue as of C++17; // X() prvalue is converted to xvalue Temporary materialization occurs in the following situations: when binding a reference to a prvalue when performing a member access on a class prvalue when performing an array-to-pointer conversion (see above) or subscripting on an array prvalue when initializing an object of type std::initializer_list<T> from a braced-init-list when typeid is applied to a prvalue (this is part of an unevaluated expression) when sizeof is applied to a prvalue (this is part of an unevaluated expression) when a prvalue appears as a discarded-value expression

(since C++17)

  • 何时绑定引用到prvalue
  • 在执行成员访问关于类prvalue
  • 执行数组到指针转换%28时,请参阅%29以上或订阅在数组prvalue上
  • 初始化类型对象时std::initializer_list<T>从带括号的列表
  • 何时类型应用于prvalue%28,这是未计算表达式%29的一部分。
  • 何时大小应用于prvalue%28,这是未计算表达式%29的一部分。
  • 当prvalue显示为废弃值表达式

%28自C++17%29

函数到指针

安洛值功能类型T可以隐式转换为prvalue指向该函数的指针这不适用于非静态成员函数,因为引用非静态成员函数的值不存在。

数字晋升

积分提升

prvalue小积分类型%28,如char%5月29日转换为较大整数类型的prvalue%28,如int29%。特别是,算术算子不接受小于int作为参数,和积分晋升自动应用后,lvalue-rvalue转换,如果适用的话.。此转换始终保留该值。

下列隐含转换被归类为整体晋升:

  • signed charsigned short可以转换为int
  • unsigned charunsigned short可以转换为int如果它能够保持其整个值范围,并且unsigned int否则;
  • char可以转换为intunsigned int取决于基本类型:signed charunsigned char%28见%29以上;
  • wchar_t,,,char16_t,和char32_t可以从以下列表中将其转换为第一种类型,以保存其整个值范围:int,,,unsigned int,,,long,,,unsigned long,,,long long,,,unsigned long long
  • 非作用域枚举基础类型未固定的类型可以从以下列表中转换为第一种类型,该列表能够保存其整个值范围:int,,,unsigned int,,,long,,,unsigned long,,,long long,或unsigned long long,扩展整数类型%28的大小顺序,自C++11%29以来,有符号优先于%29%28。如果价值范围较大,则不适用整体晋升;

an unscoped enumeration type whose underlying type is fixed can be converted to its underlying type, and, if the underlying type is also subject to integral promotion, to the promoted underlying type;

(since C++11)

  • 非作用域枚举基础类型固定的类型可以转换为其基础类型,如果基础类型也受整体提升的限制,则转换为升级的基础类型;%28自C++11%29
  • 位场类型可以转换为int如果它可以表示位字段的整个值范围,则为unsigned int如果它能代表比特字段的整个值范围,否则就不适用整体提升;
  • 类型bool可以转换为int有价值false?0?true1...

请注意,所有其他转换都不是晋升;例如,过载分辨率选char->int28%晋升人数超过29人char->short转换率%28%29。

浮点推广

阿prvalue类型float可以转换为类型的prvalue。double值不变。

数值转换

与促销不同的是,数值转换可能会改变值,从而导致精度的潜在损失。

积分变换

阿prvalue可以将整数类型或非作用域枚举类型转换为任何其他整数类型。如果转换列在整体晋升项下,则为升级而非转换。

  • 如果目标类型是无符号的,则结果值是等于源值的最小无符号值。模数2N 其中n是用来表示目标类型的位数。也就是说,取决于目标类型是更宽还是更窄,有符号整数是符号扩展的。[脚注1]或截断整数和无符号整数分别为零扩展或截断.
  • 如果目标类型有符号,则如果源整数可以在目标类型中表示,则值不会更改。否则,结果是实现定义的。%28请注意,这与符号整数算术溢出,它是未定义的%29。
  • 如果源类型为bool,价值false被转换为零和值。true转换为目标类型%28中的值之一--注意,如果目标类型是int,这是整数提升,而不是整数转换%29。
  • 如果目标类型是bool,这是一个布尔转换%28,参见%29下面。

浮点变换

阿prvalue浮点类型的值可以转换为任何其他浮点类型的prvalue。如果转换列在浮点数促销项下,则它是晋升而不是转换。

  • 如果源值可以准确地以目标类型表示,则不会更改。
  • 如果源值介于目标类型的两个可表示值之间,则结果是这两个值%28中的一个--它是实现定义的,尽管支持ieee算术,但舍入是默认的。到最近29%。
  • 否则,行为就没有定义。

浮动积分变换

  • 阿prvalue浮点类型的值可以转换为任何整数类型的prvalue。小数部分被截断,即小数部分被丢弃。如果该值不能与目标类型相匹配,则即使目标类型未带符号,该行为也是未定义的%28,则模算法不应用%29。如果目标类型是bool,这是一个布尔转换%28,参见%29下面。
  • 整数或非作用域枚举类型的prvalue可以转换为任何浮点类型的prvalue。如果值不能正确表示,则实现定义了是否选择最近的更高值还是最近的较低可表示值,尽管如果支持ieee算法,则舍入缺省值。到最近如果值不能符合目标类型,则行为未定义。如果源类型为bool,价值false被转换为零,并且值true被转换成一个。

指针转换

  • 空指针常数28%见NULL%29可以转换为任何指针类型,其结果是该类型的空指针值。这类转换率为28%空指针转换%29允许作为单个转换转换为cv限定类型,也就是说,它%27s不被认为是数字转换和限定转换的组合。
  • 阿prvalue指向任意%28(Cv)限定%29对象类型的指针。T可以转换为指向%28同名cv限定%29的prvalue指针。void结果指针表示内存中与原始指针值相同的位置。如果原始指针是空指针值,则结果是目标类型的空指针值。
  • 指向%28可选cv限定%29派生类类型的prvalue指针可以转换为指向其%28相同cv限定%29基类的prvalue指针。如果基类不可访问或模棱两可,则转换为格式错误的%28元%27T编译%29。转换的结果是指向指向对象内的基类子对象的指针。空指针值转换为目标类型的空指针值。

指针到成员转换

  • 空指针常数28%见NULL%29可以转换为任何指针到成员类型,其结果是该类型的空成员指针值。这类转换率为28%空成员指针转换%29允许作为单个转换转换为cv限定类型,也就是说,它%27s不被认为是数字转换和限定转换的组合。
  • 阿prvalue指向某种类型的成员的指针T在基类中B可以转换为prvalue指向同一类型成员的指针。T在其派生类中D.如果B是不可访问的、模棱两可的或虚拟的D的中间虚拟库的基。D,转换为格式错误的%28元%27T编译%29。结果指针可以用D对象中访问该成员。B底座D对象。空指针值转换为目标类型的空指针值。

布尔变换

阿prvalue可以将整数、浮点、非作用域枚举、指针和指针到成员类型的值转换为类型的prvalue。bool...

整数、浮点和非作用域枚举%29的值为零%28,空指针和空指针到成员值变为空值。false.所有其他价值true...

A prvalue of type std::nullptr_t, including nullptr, can be converted to a prvalue of type bool in context of direct-initialization. The resulting value is false.

(since C++11)

资格转换

  • 阿prvalue类型指针的简历-合格类型T可以转换为指向更多cv限定的相同类型的prvalue指针。T%28换句话说,稳定性和波动性可以添加%29。
  • 指向cv限定类型成员的类型指针的prvalue。T上课时X可以转换为更多cv限定类型的成员的prvalue指针。T上课时X...

“更多的”简历-合格的意思是。

  • 指向不合格类型可以转换为指向const
  • 指向不合格类型可以转换为指向volatile
  • 指向不合格类型可以转换为指向const volatile
  • 指向const类型可以转换为指向const volatile
  • 指向volatile类型可以转换为指向const volatile...

对于多级指针,适用以下限制:多级指针P1就是CV1

指向CV1的限定指针

1-指向...CV1的限定指针

n-1-指向cv1的限定指针

n-合格T可转换为多级指针。P2就是CV2

指向CV2的限定指针

1-指向...CV2的限定指针

n-1-cv2限定指针

n-合格T除非。

  • 级别数n两个指针相同;
  • 如果有一个const在CV1中

K资格在某种级别%28,而不是P1的零级%29,有一个const在同一级别的CV2中

k为P2;

  • 如果有一个volatile在CV1中 K资格在某种级别%28,而不是P1的零级%29,有一个volatile在同一个CV2中 K级P2;
  • 如果在某种程度上kP2再多点简历-合格P1,那么一定有一个const的每一级%28,而不是零级%29P2一直到k:CV2

1,CV2

2...CV2

k.

  • 同样的规则适用于成员的多层指针和对象和成员的多层混合指针;同样的规则适用于多层指针,其中包括指向任意级别上已知或未知界限数组的指针--限定元素的数组被认为是相同的cv-限定自己%29;%28自C++14%29
  • 同样的规则适用于多层指针,其中包括指向任意级别上已知或未知界限数组的指针--限定元素的数组被认为是相同的cv-限定自己%29;

%28自C++14%29

  • 零级由非多级限定转换规则处理。二次char** p = 0; const char** p1 = p; // error: level 2 more cv-qualified but level 1 is not const const char* const * p2 = p; // OK: level 2 more cv-qualified and const added at level 1 volatile char * const * p3 = p; // OK: level 2 more cv-qual and const added at level 1 volatile const char* const* p4 = p2; // OK: 2 more cv-qual and const was already at 1 double *a[2][3]; double const * const (*ap)[3] = a; // OK since C++14二次请注意,在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指针。空率%28%2AP%29%28%29;无效%28%2A%2APP%29%28%29 no=&p;//Error:无法将指针转换为no函数结构S{tyduf void%28%2AP%29%28%29;运算符p%28%29;};void%28%2AQ%29%28%29 no=S%28%29;//Error:无法将指针转换为no函数%28自C++17%29
  • 阿prvalue可以将指向非抛出函数的类型指针转换为指向潜在抛出函数的prvalue指针。
  • 指向非抛出成员函数的类型指针的prvalue可以转换为指向潜在抛出成员函数的prvalue指针。

空率%28%2AP%29%28%29;无效%28%2A%2APP%29%28%29 no=&p;//Error:无法将指针转换为no函数结构S{tyduf void%28%2AP%29%28%29;运算符p%28%29;};void%28%2AQ%29%28%29 no=S%28%29;//Error:无法将指针转换为no函数

%28自C++17%29

安全问题

在C++11中引入显式转换函数之前,设计一个在布尔上下文中可以使用的类(%28e.g)。if(obj) { ... }%29出现了一个问题:给定用户定义的转换函数,如T::operator bool() const;,隐式转换序列允许在该函数调用之后增加一个标准转换序列,这意味着bool可以转换为int,允许这样的代码obj << 1;int i = obj;...

这方面的一个早期解决方案可以在std::basic_ios,它定义了operator!operator void*%28,直到C++11%29,以便代码如if(std::cin){...}编译是因为void*可转换为bool,但是int n =std::cout;不编译,因为void*不可兑换为int.这仍然允许无意义的代码,例如deletestd::cout;为了编译,许多预C++11第三方库都是用更详细的解决方案设计的,称为安全Bool成语...

The explicit bool conversion can also be used to resolve the safe bool problem. explicit operator bool() const { ... }

(since C++11)

脚注

  1. 这只适用于算术为2%27s的补码,这是只需要精确宽度整数类型不过,请注意,目前所有使用C++编译器的平台都使用2%27 s的补码算法。缺陷报告以下行为更改缺陷报告追溯应用于先前发布的C++标准。博士适用于公布的行为正确行为CWG 616C++11任何未初始化对象的lvalue到rvalue转换总是ub。允许不确定的无符号字符CWG 1423C++11STD::nullptr[医]t在直接初始化和复制初始化中都可以转换为bool。直接初始化CWG 330C++14转换成双倍%2AConst%28%2AP%29三双康%2AConst%28%2AP%29三无效转换有效另见
  1. 康斯特[医]铸造
  1. 静态[医]铸造
  1. 动态[医]铸造
  1. 重释[医]铸造
  1. 显式铸造
  1. 用户定义转换

隐式转换的C文档

*。

代码语言:txt
复制
 ? cppreference.com

在CreativeCommonsAttribution下授权-ShareAlike未移植许可v3.0。

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com