精华内容
下载资源
问答
  • 隐式类型转换有无法命中索引的风险,在高并发、大数据量的情况下,命不中索引带来的后果非常严重。下面这篇文章主要给大家整理总结了关于MySQL的隐式转化,需要的朋友可以参考借鉴,下面来一起看看吧。
  • 主要介绍了scala中的隐式类型转换的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • C 语言隐式类型转换规则 C语言规定,不同类型的数据需要转换成同一类型后才可进行计算,在整型实型和字符型数据之间通过类型 转换便可以进行混合运算(但不是所有类型之间都可以进行转换) .当混合不同类型的变量进行...
  • 主要介绍了JS面试题大坑之隐式类型转换实例代码,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
  • 主要介绍了C++隐式类型转换运算符operator type()用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 本文将要为您介绍的是Mysql隐式类型转换原则,具体实现方法:  MySQL 的隐式类型转换原则:  - 两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=> 对两个 NULL 做比较时会返回 1,这两种...
  • 本文实例讲述了JavaScript强制类型转换和隐式类型转换。分享给大家供大家参考,具体如下: 在JavaScript中声明变量不需指定类型, 对变量赋值也没有类型检查,同时JavaScript允许隐式类型转换。这些特征说明...
  • 本文实例讲述了JavaScript隐式类型转换操作。分享给大家供大家参考,具体如下: JavaScript的数据类型是非常弱的(不然不会叫它做弱类型语言了)!在使用算术运算符时,运算符两边的数据类型可以是任意的,比如,一...
  • 主要介绍了c++隐式类型转换的二个示例,需要的朋友可以参考下
  • 这个问题大致是这样的,本来试图写一个产生低8位为1的掩码的语句: uint32_t mask = ~((uint8_t)0); ,结果发现算出的掩码是 0xffffffff 显然不符合预期,于是折腾检查了一番,写出对比程序如下: ...
  • 隐式类型转换

    千次阅读 2019-03-07 20:55:57
    隐式类型转换 定义: C++ 的基本类型中并非是完全的对立,部分数据类型之间是可以进行隐式转换的。隐式转换指的是不需要用户干预,编译器私下进行的类型转换行为。很多时候用户可能都不知道发生了哪些转换。 为何要...

    隐式类型转换

    定义:

    C++ 的基本类型中并非是完全的对立,部分数据类型之间是可以进行隐式转换的。隐式转换指的是不需要用户干预,编译器私下进行的类型转换行为。很多时候用户可能都不知道发生了哪些转换。

    为何要进行隐式转换:

    C++ 面向对象的多态性,就是通过父类的类型实现对子类的封装。通过隐式转换,你可以直接将一个子类的对象使用父类的类型进行返回。…又或者数值和布尔类型的转换,整数和浮点数的转换等。

    C++ 隐式转换的原则:

    基本数据类型的转换以低精度到高精度,即保证精度不丢失。如:char 到 int,int 到 long。
    自定义对象:子类对象可隐式的转换为父类对象。

    C++ 隐式转换发生条件:

    混合类型的算术运算表达式中;

    int a = 3;
    double b = 4.5;
    double c = a + b;     // a 将被自动转换为 double 类型,再加法。
    

    不同类型的赋值操作中;

    int a = true;         // bool 类型转换为 int 类型
    int *ptr = null;      // null 被转换为 int * 类型
    
    **函数参数传值;**
    ```c
    void func(double a) {};
    func(1);               // 1 被隐式的转换为 double 类型1.0
    

    函数返回值:

    double add(int a, int b)
    {
        return a + b;      // 运算的结果会被隐式的转换为 double 类型再返回
    }
    

    强制类型转换:

    double a = 2.0;        // 会损失精度,可能带来潜在的错误
    int b = (int)a;
    

    隐式转换的风险:

    隐式转换的风险一般存在于自定义的类构造函数中。 按照默认规定,只有一个参数的构造函数也定义了一个隐式转换,将该构造函数对应数据类型的数据转换为该类对象。
    如:

    class String
    {
    public:
        String (const char* p);       // 用 C 风格的字符串p作为初始化值
    }
    ...
    String s1 = "hello";              // OK 隐式转换,等价于 String s1 = String("hello")
    
    但是有时可能会不需要这种隐式转换,如:
    class String
    {
    public:
        String( int n);               // 本意是预先分配 n 个字节给字符串
        String( const char* p);       // 用 C 风格的字符串 p 作为初始化值
    }
    ...
    String s2(10);                    // OK 分配10个字节的空字符串
    String s3 = String(10);           // OK 分配10个字节的空字符串
    
    String s4 = 10;                  // 编译通过,也是分配10个字节的空字符串
    String s5 = 'a';                 // 编译通过,分配 int('a') 个字节的空字符串
    // s4 和 s5 分别把一个 int 型和 char 型,隐式转换成了分配若干字节的空字符串,容易令人误解。
    
    class Test
    {
    public:
        Test(int a);
        bool isSame(Test other)
        {
            return m_val == other.m_val;
        }
    private:
        int m_val;    
    }
    
    Test a(10);
    if(a.isSame(10));                   // 该语句将返回true
    

    本来用于两个Test对象的比较,对象 a 竟然和 int 类型相等了。这就是由于发生了隐式转换,实际上进行比较的是一个临时的 Test 对象。发生了异常。

    禁止隐式转换:explicit

    c++ 中的 explicit 关键字只能用于修饰只有一个参数的类构造函数,即作用为:禁止隐式调用类内的单参数构造函数。

    1. 该关键字只能用来修饰类内部的构造函数
    2. 禁止隐式调用拷贝构造函数
    3. 禁止类对象之间的隐式转换
    class Test
    {
        explicit Test(int a);
    }
    
    Test aa(10);                         // OK 
    Test aa = 10;                        // 非法,此操作被禁止。加入explicit 可以有效的防止隐式转换的发生,提高程序质量。
    Test bb = aa;                        // 非法,取消了隐式转换,除非重载操作符“=”
    

    Google的C++规范中建议使用 explicit 关键字。effective C++ 中说,被声明为 explicit 的构造函数通常比其 non-explicit 兄弟更受欢迎。
    【参考文献】
    https://www.cnblogs.com/solidblog/p/3381628.html

    展开全文
  • 在我们采用反射动态调用一些方法时,常常涉及到类型转换,直接判断类型是否相符有时不能判断调用方法是否合适
  • C++: 隐式类型转换和显式类型转换

    千次阅读 2019-11-06 12:49:44
    隐式类型转换 又称为“标准转换”,包括以下几种情况: 1) 算术转换(Arithmetic conversion) : 在混合类型的算术表达式中, 最宽的数据类型成为目标转换类型。 intival=3; doubledval=3.14159; ival+dval;//ival...

     

    第1部分. 隐式类型转换


    又称为“标准转换”,包括以下几种情况:
    1) 算术转换(Arithmetic conversion) : 在混合类型的算术表达式中, 最宽的数据类型成为目标转换类型。

    int ival = 3;
    double dval = 3.14159;
    
    ival + dval;//ival被提升为double类型

    2)一种类型表达式赋值给另一种类型的对象:目标类型是被赋值对象的类型

    int *pi = 0; // 0被转化为int *类型
    ival = dval; // double->int

    例外:void指针赋值给其他指定类型指针时,不存在标准转换,编译出错

    3)将一个表达式作为实参传递给函数调用,此时形参和实参类型不一致:目标转换类型为形参的类型

    extern double sqrt(double);

    cout << "The square root of 2 is " << sqrt(2) << endl;
    //2被提升为double类型:2.0

    4)从一个函数返回一个表达式,表达式类型与返回类型不一致:目标转换类型为函数的返回类型

    double difference(int ival1, int ival2)
    {
        return ival1 - ival2;
        //返回值被提升为double类型
    }

     

    第2部分. 显式类型转换


    被称为“强制类型转换”(cast)
    C     风格: (type-id)
    C++风格: static_castdynamic_castreinterpret_cast、和const_cast..

     

    关于强制类型转换的问题,很多书都讨论过,写的最详细的是C++ 之父的《C++ 的设计和演化》。最好的解决方法就是不要使用C风格的强制类型转换,而是使用标准C++的类型转换符:static_cast, dynamic_cast。标准C++中有四个类型转换符:static_castdynamic_castreinterpret_cast、和const_cast。下面对它们一一进行介绍。
     

    static_cast

     

    用法:static_cast < type-id > ( expression )

     

    说明:该运算符把expression转换为type-id类型,但没有运行时类型检查来保证转换的安全性。

     

    来源:为什么需要static_cast强制转换?
    情况1:void指针->其他类型指针
    情况2:改变通常的标准转换
    情况3:避免出现可能多种转换的歧义




    它主要有如下几种用法:
    • 用于类层次结构中基类和子类之间指针或引用的转换。进行上行转换(把子类的指针或引用转换成基类表示)是安全的;进行下行转换(把基类指针或引用转换成子类指针或引用)时,由于没有动态类型检查,所以是不安全的。
    • 用于基本数据类型之间的转换,如把int转换成char,把int转换成enum。这种转换的安全性也要开发人员来保证。
    • 把void指针转换成目标类型的指针(不安全!!)
    • 把任何类型的表达式转换成void类型。
    注意:static_cast不能转换掉expression的const、volitale、或者__unaligned属性。
     

    dynamic_cast

     

    用法:dynamic_cast < type-id > ( expression )

     

    说明:该运算符把expression转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;如果type-id是类指针类型,那么expression也必须是一个指针,如果type-id是一个引用,那么expression也必须是一个引用。


    来源:为什么需要dynamic_cast强制转换?
    简单的说,当无法使用virtual函数的时候

    典型案例:
    Wicrosoft公司提供给我们一个类库,其中提供一个类Employee.以头文件Eemployee.h和类库.lib分发给用户
    显然我们并无法得到类的实现的源代码
    //Emplyee.h
    class Employee 
    {
    public:
        virtual int salary();
    };
    
    class Manager : public Employee
    {
    public: 
        int salary();
    };
    
    class Programmer : public Employee
    {
    public:
        int salary();
    };

    我们公司在开发的时候建立有如下类:
    class MyCompany
    {
    public:
        void payroll(Employee *pe);
        //
    };
    
    void MyCompany::payroll(Employee *pe)
    {
        //do something
    }

    但是开发到后期,我们希望能增加一个bonus()的成员函数到W$公司提供的类层次中。
    假设我们知道源代码的情况下,很简单,增加虚函数:
    //Emplyee.h
    class Employee 
    {
    public:
        virtual int salary();
        virtual int bonus();
    };
    
    class Manager : public Employee
    {
    public: 
        int salary();
    };
    
    class Programmer : public Employee
    {
    public:
        int salary();
        int bonus();
    };
    
    //Emplyee.cpp
    
    int Programmer::bonus()
    {
        //
    }
    
    
    payroll()通过多态来调用bonus()
    class MyCompany
    {
    public:
        void payroll(Employee *pe);
        //
    };
    
    void MyCompany::payroll(Employee *pe)
    {
        //do something
        //pe->bonus();
    }

    但是现在情况是,我们并不能修改源代码,怎么办?dynamic_cast华丽登场了!
    在Employee.h中增加bonus()声明,在另一个地方定义此函数,修改调用函数payroll().重新编译,ok

     

    //Emplyee.h
    class Employee 
    {
    public:
        virtual int salary();
    };
    
    class Manager : public Employee
    {
    public: 
        int salary();
    };
    
    class Programmer : public Employee
    {
    public:
        int salary();
        int bonus();//直接在这里扩展
    };
    
    //somewhere.cpp
    
    int Programmer::bonus()
    {
        //define
    }
    
     
    class MyCompany
    {
    public:
        void payroll(Employee *pe);
        //
    };
    
    void MyCompany::payroll(Employee *pe)
    {
        Programmer *pm = dynamic_cast<Programmer *>(pe);
        
        //如果pe实际指向一个Programmer对象,dynamic_cast成功,并且开始指向Programmer对象起始处
        if(pm)
        {
            //call Programmer::bonus()
        }
        //如果pe不是实际指向Programmer对象,dynamic_cast失败,并且pm = 0
        else
        {
            //use Employee member functions
        }
    }
    
    

    dynamic_cast主要用于类层次间的上行转换和下行转换,还可以用于类之间的交叉转换。

    在类层次间进行上行转换时,dynamic_cast和static_cast的效果是一样的;在进行下行转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。
    class Base
    {
    public:
        int m_iNum;
        virtual void foo();
    };
    
    class Derived:public Base
    {
    public:
        char *m_szName[100];
    };
    
    void func(Base *pb)
    {
        Derived *pd1 = static_cast<Derived *>(pb);
    
        Derived *pd2 = dynamic_cast<Derived *>(pb);
    }

    在上面的代码段中,
    如果pb实际指向一个Derived类型的对象,pd1和pd2是一样的,并且对这两个指针执行Derived类型的任何操作都是安全的;
    如果pb实际指向的是一个Base类型的对象,那么pd1将是一个指向该对象的指针,对它进行Derived类型的操作将是不安全的(如访问m_szName),而pd2将是一个空指针(即0,因为dynamic_cast失败)。
    另外要注意:Base要有虚函数,否则会编译出错;static_cast则没有这个限制。这是由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表(关于虚函数表的概念,详细可见<Inside c++ object model>)中,只有定义了虚函数的类才有虚函数表,没有定义虚函数的类是没有虚函数表的。

    另外,dynamic_cast还支持交叉转换(cross cast)。如下代码所示。
    class Base
    {
    public:
        int m_iNum;
        virtual void f(){}
    };
    
    
    
    class Derived1 : public Base
    {
    
    };
    
    class Derived2 : public Base
    {
    
    };
    
    void foo()
    {
        derived1 *pd1 = new Drived1;
    
        pd1->m_iNum = 100;
    
        Derived2 *pd2 = static_cast<Derived2 *>(pd1); //compile error
    
        Derived2 *pd2 = dynamic_cast<Derived2 *>(pd1); //pd2 is NULL
    
        delete pd1;
    }

    在函数foo中,使用static_cast进行转换是不被允许的,将在编译时出错;而使用 dynamic_cast的转换则是允许的,结果是空指针。
     

    reinpreter_cast

     

    用法:reinpreter_cast<type-id> (expression)

     

    说明:type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,在把该整数转换成原类型的指针,还可以得到原先的指针值)。



    该运算符的用法比较多。
     

    const_cast

     

    用法:const_cast<type_id> (expression)

     

    说明:该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和expression的类型是一样的。



    常量指针被转化成非常量指针,并且仍然指向原来的对象;常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。

    Voiatile和const类试。举如下一例:

    class B{
    
    public:
    int m_iNum;
    }
    
    void foo(){
    const B b1;
    b1.m_iNum = 100; //comile error
    B b2 = const_cast<B>(b1);
    b2. m_iNum = 200; //fine
    }


    上面的代码编译时会报错,因为b1是一个常量对象,不能对它进行改变;使用const_cast把它转换成一个常量对象,就可以对它的数据成员任意改变。注意:b1和b2是两个不同的对象。

    展开全文
  • ORACLE隐式类型转换

    2020-11-23 15:21:17
    隐式类型转换简介 通常ORACLE数据库存在显式类型转换(Explicit Datatype Conversion)和隐式类型转换(Implicit Datatype Conversion)两种类型转换方式。如果进行比较或运算的两个值的数据类型不同时(源数据的...

     

    隐式类型转换简介

     

    通常ORACLE数据库存在显式类型转换(Explicit Datatype Conversion和隐式类型转换(Implicit Datatype Conversion)两种类型转换方式。如果进行比较或运算的两个值的数据类型不同时(源数据的类型与目标数据的类型),而且此时又没有转换函数时,那么ORACLE必须将其中一个值进行类型转换,使其能够运算。这就是所谓的隐式类型转换。其中隐式类型转换是自动进行的,当然,只有在这种转换是有意义的时候,才会自动进行。

     

    Data Conversion

    Generally an expression cannot contain values of different datatypes. For example, an expression cannot multiply 5 by 10 and then add 'JAMES'. However, Oracle supports both implicit and explicit conversion of values from one datatype to another.

     

     

    关于隐式类型转换,建议翻看官方文档Data Type Comparison Rules章节,下面是官方文档中的隐式类型转换矩阵。从下面这个表格,我们就能对哪些数据类型能进行转换一目了然。

     

    clip_image001[4]

     

     

     

     

    隐式转换的规则:

     

     

    其实隐式类型转换发生在很多地方,只是我们很多时候没有留意罢了,不打算一一举例,自行翻阅官方文档的介绍,摘抄隐式类型转换的一些常见的规则如下:

     

    The following rules govern implicit data type conversions:

    • During INSERT and UPDATE operations, Oracle converts the value to the data type of the affected column.
    • During SELECT FROM operations, Oracle converts the data from the column to the type of the target variable.
    • When manipulating numeric values, Oracle usually adjusts precision and scale to allow for maximum capacity. In such cases, the numeric data type resulting from such operations can differ from the numeric data type found in the underlying tables.
    • When comparing a character value with a numeric value, Oracle converts the character data to a numeric value.
    • Conversions between character values or NUMBER values and floating-point number values can be inexact, because the character types and NUMBER use decimal precision to represent the numeric value, and the floating-point numbers use binary precision.
    • When converting a CLOB value into a character data type such as VARCHAR2, or converting BLOB to RAW data, if the data to be converted is larger than the target data type, then the database returns an error.
    • During conversion from a timestamp value to a DATE value, the fractional seconds portion of the timestamp value is truncated. This behavior differs from earlier releases of Oracle Database, when the fractional seconds portion of the timestamp value was rounded.
    • Conversions from BINARY_FLOAT to BINARY_DOUBLE are exact.
    • Conversions from BINARY_DOUBLE to BINARY_FLOAT are inexact if the BINARY_DOUBLE value uses more bits of precision that supported by the BINARY_FLOAT.
    • When comparing a character value with a DATE value, Oracle converts the character data to DATE.
    • When you use a SQL function or operator with an argument of a data type other than the one it accepts, Oracle converts the argument to the accepted data type.
    • When making assignments, Oracle converts the value on the right side of the equal sign (=) to the data type of the target of the assignment on the left side.
    • During concatenation operations, Oracle converts from noncharacter data types to CHAR or NCHAR.
    • During arithmetic operations on and comparisons between character and noncharacter data types, Oracle converts from any character data type to a numeric, date, or rowid, as appropriate. In arithmetic operations between CHAR/VARCHAR2 and NCHAR/NVARCHAR2, Oracle converts to a NUMBER.
    • Most SQL character functions are enabled to accept CLOBs as parameters, and Oracle performs implicit conversions between CLOB and character types. Therefore, functions that are not yet enabled for CLOBs can accept CLOBs through implicit conversion. In such cases, Oracle converts the CLOBs to CHAR or VARCHAR2 before the function is invoked. If the CLOB is larger than 4000 bytes, then Oracle converts only the first 4000 bytes to CHAR.
    • When converting RAW or LONG RAW data to or from character data, the binary data is represented in hexadecimal form, with one hexadecimal character representing every four bits of RAW data. Refer to "RAW and LONG RAW Data Types" for more information.
    • Comparisons between CHAR and VARCHAR2 and between NCHAR and NVARCHAR2 types may entail different character sets. The default direction of conversion in such cases is from the database character set to the national character set. Table 2-9 shows the direction of implicit conversions between different character types.

     

    对上面官方文档资料的翻译如下,如有不对或不够确切的地方,敬请指出

     

    1.  对于INSERTUPDATE操作,ORACLE会把插入值或者更新值隐式转换为对应字段的数据类型。

     

    2.  对于SELECT语句,ORACLE会把字段的数据类型隐式转换为变量的数据类型。

     

    3.  当处理数值时,ORACLE通常会调整精度和小数位,以实现最大容量。在这种情况下,由此类操作产生的数字数据类型可能与在基础表中找到的数字数据类型不同。

     

    4.  当比较一个字符型和数值型的值时,ORACLE会把字符型的值隐式转换为数值型。

     

    5.  字符值或NUMBER值与浮点数值之间的转换可能不准确,因为字符类型和NUMBER使用十进制精度表示数字值,而浮点数则使用二进制精度。

     

    6.  CLOB值转换为字符数据类型(例如VARCHAR2)或将BLOB转换为RAW数据时,如果要转换的数据大于目标数据类型,则数据库将返回错误。

     

    7.   timestamp类型转换为DATE时(按照第三条,隐式转换不应该把timestamp转换为date,除非insert这样的),timestamp后几位会被truncated忽略,至于忽略几位,取决于数据库版本。

     

    8.  BINARY_FLOATBINARY_DOUBLE的转换是准确的。

     

    9.  BINARY_DOUBLEBINARY_FLOAT的转换是不精确的,因为BINARY_DOUBLE精度更高。

     

    10.  当比较字符型和日期型的数据时,ORACLE会把字符型转换为日期型。

     

    11. 如果调用函数(过程)或运算符操作时,如果输入参数的数据类型与函数(存储过程)定义的参数数据类型不一致或不是可接受的数据类型时,则ORACLE会把输入参数的数据类型转换为函数或者过程定义的数据类型。

     

    12. 当使用赋值符号(等号)时,右边的类型转换为左边的类型

     

    13. 当连接操作(concatenation,一般为||)时,ORACLE会隐式转换非字符型到字符型

     

    14. 如果字符类型的数据和非字符类型的数据(numberdaterowid)作算术运算,则ORACLE会将字符类型的数据转换为合适的数据类型,这些数据类型可能是numberdaterowid等。

      如果CHAR/VARCHAR2 NCHAR/NVARCHAR2之间作算术运算,则ORACLE会将她们都转换为number类型的数据再做比较。

     

     

    15. 比较CHAR/VARCHAR2 NCHAR/NVARCHAR2时,如果两者字符集不一样,则默认的转换方式是将数据编码从数据库字符集转换为国家字符集

     

     

    下面简单举两个例子,看看隐式转换发生的场景:

     

    例子:

     

    SQL> create table test(object_id varchar2(12), object_name varchar2(64));
     
    Table created.
     
    SQL> insert into test
      2  select object_id, object_name from dba_objects;
     
    63426 rows created.
     
    SQL> commit;
     
    Commit complete.
     
    SQL> create index ix_test_n1 on test(object_id);
     
    Index created.
     
    SQL> select count(*) from test where object_id=20;
     
      COUNT(*)
    ----------
             1
     
    SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
     
    PLAN_TABLE_OUTPUT
    -------------------------------------------------------------------------------
    SQL_ID  4bh7yzj5ma0ks, child number 0
    -------------------------------------
    select count(*) from test where object_id=20
     
    Plan hash value: 1950795681
     
    ---------------------------------------------------------------------------
    | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    ---------------------------------------------------------------------------
    |   0 | SELECT STATEMENT   |      |       |       |    45 (100)|          |
    |   1 |  SORT AGGREGATE    |      |     1 |     8 |            |          |
     
    PLAN_TABLE_OUTPUT
    -------------------------------------------------------------------------------
    |*  2 |   TABLE ACCESS FULL| TEST |     3 |    24 |    45  (20)| 00:00:01 |
    ---------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       2 - filter(TO_NUMBER("OBJECT_ID")=20)
     
    Note
    -----
       - dynamic sampling used for this statement
     
    PLAN_TABLE_OUTPUT
    -------------------------------------------------------------------------------------
     
    23 rows selected.

     

    如上所示,这个发生隐式转换是因为这个规则: 当比较一个字符型和数值型的值时,ORACLE会把字符型的值隐式转换为数值型(对于SELECT语句,ORACLE会把字段的数据类型隐式转换为变量的数据类型。似乎这个规则也对),此时由于隐式转换发生在OBJECT_ID字段上(TO_NUMBER("OBJECT_ID"),导致执行计划走全表扫描。如果我们稍微修改一下SQL的写法,就会发现执行计划会走INDEX RANGE SCAN。 如下所示:

     

    SQLselect count(*) from test where object_id='20';
     
      COUNT(*)
    ----------
             1
     
    SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
     
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    SQL_ID  7800f6da7c909, child number 0
    -------------------------------------
     select count(*) from test where object_id='20'
     
    Plan hash value: 4037411162
     
    --------------------------------------------------------------------------------
    | Id  | Operation         | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
    --------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT  |            |       |       |     1 (100)|          |
    |   1 |  SORT AGGREGATE   |            |     1 |     6 |            |          |
     
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    |*  2 |   INDEX RANGE SCAN| IX_TEST_N1 |     1 |     6 |     1   (0)| 00:00:01 |
    --------------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       2 - access("OBJECT_ID"='20')
     
     
    19 rows selected.

     

    下面再介绍一个案例(当比较字符型和日期型的数据时,ORACLE会把字符型转换为日期型。),这种转换虽然大部分情况下都是正常的,但是有时候会成为一个隐藏的逻辑炸弹,当NLS_DATE_FORMAT环境变量改变时,则有可能出现错误或逻辑错误。

     

    SQL> SELECT *
      2  FROM scott.emp
      3  WHERE hiredate between '01-JAN-1981' and '01-APR-1981';
     
         EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO
    ---------- ---------- --------- ---------- --------- ---------- ---------- ----------
          7499 ALLEN      SALESMAN        7698 20-FEB-81       1600        300         30
          7521 WARD       SALESMAN        7698 22-FEB-81       1250        500         30
     
    SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
     
    PLAN_TABLE_OUTPUT
    ----------------------------------------------------------------------------------
    SQL_ID  czyc76busj56d, child number 0
    -------------------------------------
    SELECT * FROM scott.emp WHERE hiredate between '01-JAN-1981' and
    '01-APR-1981'
     
    Plan hash value: 3956160932
     
    --------------------------------------------------------------------------
    | Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    --------------------------------------------------------------------------
    |   0 | SELECT STATEMENT  |      |       |       |     2 (100)|          |
     
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------
    |*  1 |  TABLE ACCESS FULL| EMP  |     2 |    74 |     2   (0)| 00:00:01 |
    --------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       1 - filter(("HIREDATE"<=TO_DATE(' 1981-04-01 00:00:00', 'syyyy-mm-dd
                  hh24:mi:ss') AND "HIREDATE">=TO_DATE(' 1981-01-01 00:00:00',
                  'syyyy-mm-dd hh24:mi:ss')))
     
     
    21 rows selected.

     

     

     

     

    隐式类型转换问题

     

     

    Implicit and Explicit Data Conversion

     

    Oracle recommends that you specify explicit conversions, rather than rely on implicit or automatic conversions, for these reasons:

     

    ·         SQL statements are easier to understand when you use explicit datatype conversion functions.

     

    ·         Implicit datatype conversion can have a negative impact on performance, especially if the datatype of a column value is converted to that of a constant rather than the other way around.

     

    ·         Implicit conversion depends on the context in which it occurs and may not work the same way in every case. For example, implicit conversion from a datetime value to a VARCHAR2 value may return an unexpected year depending on the value of the NLS_DATE_FORMAT parameter.

     

    ·         Algorithms for implicit conversion are subject to change across software releases and among Oracle products. Behavior of explicit conversions is more predictable.

     

    虽然隐式转换在很多地方自动发生,但是不推荐使用隐式类型转换,Oracle官方建议指定显式类型转换,而不要依赖隐式或自动转换,主要有下面一下原因:

     

        使用显式类型转换函数时,SQL语句更易于理解。

     

        隐式类型转换可能会对性能产生负面影响,尤其是如果将列值的数据类型转换为常量而不是相反的数据类型转换操作时。

     

        隐式转换取决于发生这种转换的上下文,在不同的情况下,隐式转换的工作方式可能不同。例如,从日期时间值到VARCHAR2值的隐式转换可能会返回错误(意外)的年份,具体取决于NLS_DATE_FORMAT参数的值。

     

        隐式转换算法可能会在软件版本之间以及Oracle产品之间发生变化。明确转换的行为更容易预测。否则有可能埋下一个大坑。

     

       如果在索引表达式中发生隐式类型转换,则Oracle数据库可能不使用索引,因为它是pre-conversion data type.。这可能会对性能产生负面影响。

     

    Tom Kyte的这篇博文On Implicit Conversions and More,还总结了隐式数据类型转换会带来的一些问题:

     

     

    The resulting code typically has logic bombs in it. The code appears to work in certain circumstances but will not work in others.

    •  The resulting code relies on default settings. If someone changes the default settings, the way the code works will be subject to change. (A DBA     changing a setting can make your code work entirely differently from the way it does today.)
    •  The resulting code can very well be subject to SQL injection bugs.
    •  The resulting code may end up performing numerous unnecessary repeated conversions (negatively affecting performance and consuming many more resources than necessary).
    •  The implicit conversion may be precluding certain access paths from being available to the optimizer, resulting in suboptimal query plans. (In fact, this is exactly what is happening to you!)

        隐式转换可能会阻止某些访问路径无法用于优化器,从而导致查询计划不理想。 (实际上,这正是您数据库当中正在发生的事情!)

    •  Implicit conversions may prevent partition elimination.

     

     

        其实上面已经有相关例子介绍,下面介绍一个例子,主要用来说明,隐式类型转换不一定导致执行计划不走索引,只有当隐式转换函数出现在查询条件中的索引字段上,而且左值的类型被隐式转为了右值的类型时才会出现严重性能问题。

     

    SQL> drop table test;
     
    Table dropped.
     
    SQL> create table test
      2  as
      3  select * from dba_objects;
     
    Table created.
     
    SQL> create index ix_test_n1 on test(object_id);
     
    Index created.
     
    SQL> select count(*) from test where object_id='20';
     
      COUNT(*)
    ----------
             1
     
    SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
     
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    SQL_ID  29jmhh43kkrv4, child number 0
    -------------------------------------
    select count(*) from test where object_id='20'
     
    Plan hash value: 4037411162
     
    --------------------------------------------------------------------------------
    | Id  | Operation         | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
    --------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT  |            |       |       |     1 (100)|          |
    |   1 |  SORT AGGREGATE   |            |     1 |    13 |            |          |
     
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    |*  2 |   INDEX RANGE SCAN| IX_TEST_N1 |    10 |   130 |     1   (0)| 00:00:01 |
    --------------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       2 - access("OBJECT_ID"=20)
     
    Note
    -----
       - dynamic sampling used for this statement
     
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
     
    23 rows selected.
     
    SQL> 

     

    clip_image002[4]

     

     

    其实SQL语句发生了隐式转换,而且转换的地方在字符串’20'上面,转换为数字20。这样的变化没有发生在OBJECT_ID列上面。其次,这种转换没有发生在左值列上面,没有影响到IX_TEST_N1的路径。

     

    所以以后,如果遇到”隐式转换一定不走索引吗?”或”隐式类型转换一定导致索引失效吗?”这类问题,你都要辩证的来分析,不能一概而论。

     

     

     

    下面介绍一个绑定变量发生隐式类型转换的例子:

     

     

     

     

     

    SQL> create table test
      2  as
      3  select * from dba_objects;             
     
    Table created.
     
    SQL> commit;
     
    Commit complete.
     
    SQL> create index ix_test_object_name on test(object_name);
     
    Index created.
     
    SQL> variables v_object_name nvarchar2(30);
    SP2-0734: unknown command beginning "variables ..." - rest of line ignored.
    SQL> 
    SQL> variable v_object_name nvarchar2(30);
    SQL> exec :v_object_name :='I_OBJ1';
     
    PL/SQL procedure successfully completed.
     
    SQL> select count(*) from test where object_name=:v_object_name;
     
      COUNT(*)
    ----------
             1
     
    SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR);
     
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    SQL_ID  ft05prnxtpk9u, child number 0
    -------------------------------------
    select count(*) from test where object_name=:v_object_name
     
    Plan hash value: 1950795681
     
    ---------------------------------------------------------------------------
    | Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |
    ---------------------------------------------------------------------------
    |   0 | SELECT STATEMENT   |      |       |       |   113 (100)|          |
    |   1 |  SORT AGGREGATE    |      |     1 |    66 |            |          |
     
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
    |*  2 |   TABLE ACCESS FULL| TEST |    10 |   660 |   113  (11)| 00:00:01 |
    ---------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       2 - filter(SYS_OP_C2C("OBJECT_NAME")=:V_OBJECT_NAME)
     
    Note
    -----
       - dynamic sampling used for this statement
     
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------
     
    23 rows selected.

     

    clip_image003[4]

     

     

    这里发生隐式类型转换,是因为隐式类型规则:比较CHAR/VARCHAR2 NCHAR/NVARCHAR2时,如果两者字符集不一样,则默认的转换方式是将数据编码从数据库字符集转换为国家字符集 ,而此时是借助内部函数SYS_OP_C2C实现的

     

     

    SYS_OP_C2C is an internal function which does an implicit conversion of varchar2 to national character set using TO_NCHAR function. Thus, the filter completely changes as compared to the filter using normal comparison.

     

     

    如何找出存在隐式转换的SQL?

     

    有些公司可能对发布的SQL进行全面审计,能够从源头上杜绝大多数存在隐式类型转换的SQL,但是大多数公司可能没有这个能力或资源来实现这个目标,那么,最重要的就是如何找出数据库中存在隐式转换的SQL,关于如何找出存在隐式数据类型转换的SQL,一般有下面两个SQL:

     

     

    SELECT

         SQL_ID,

         PLAN_HASH_VALUE

     FROM

         V$SQL_PLAN X

     WHERE

         X.FILTER_PREDICATES LIKE '%INTERNAL_FUNCTION%'

     GROUP BY

         SQL_ID,

         PLAN_HASH_VALUE;

     

     

    SELECT

         SQL_ID,

         PLAN_HASH_VALUE

     FROM

         V$SQL_PLAN X

     WHERE

         X.FILTER_PREDICATES LIKE '%SYS_OP_C2C%'

     GROUP BY

         SQL_ID,

         PLAN_HASH_VALUE;

     

     

    但是需要注意的是,即使执行计划中存在INTERNAL_FUNCTION,也不一定说明SQL语句出现了隐式数据类型转换,关于这个问题,参考我的博客ORACLE数据库中执行计划出现INTERNAL_FUNCTION一定是隐式转换吗?。 所以还必须对找出的相关SQL进行仔细甄别、鉴定。

     

     

    另外,这篇博客ORACLE中内部函数SYS_OP_C2C和隐式类型转换,也值得对隐式类型转换了解不深的同学看看。

     

     

     

     

     

    如何避免隐式类型转换呢?

     

    1:在数据库设计阶段和写SQL期间,尽量遵循一致的原则,避免不必要的数据类型转换。

     

     

       在建模时,要统一字段类型,尤其是和其它表进行关联的相关字段必须保证数据类型一致。这样可以避免不必要的隐式数据类型转换。

     

     

       查询SQL中条件与字段类型保持一致,另外,确保绑定变量的数据类型。使其与对应字段的数据类型一致

     

     

    2:使用转换函数,进行显示类型转换。

     

     

    例如有下面一些常见的类型转换函数:

     

    ·         TO_CHAR:把DATENUMBER转换成字符串;

    ·         TO_DATE:把NUMBERCHARVARCHAR2转换成DATE。当用到时间戳时,可以用到TO_TIMESTAMPTO_TIMESTAMP_TZ

    ·         TO_NUMBER:  CHARVARCHAR2转换成NUMBER

     

     

    3:创建带有SYS_OP_C2C的函数索引。

     

     

    这种方法比较少用,不过确实也是特殊场景下的一种优化方法。

     

     

     

     

    参考资料:

     

    https://blogs.oracle.com/oraclemagazine/on-implicit-conversions-and-more

    https://docs.oracle.com/cd/E21764_01/apirefs.1111/e12048/cql_elements.htm#CQLLR290

    https://docs.oracle.com/en/database/oracle/oracle-database/19/sqlrf/Data-Type-Comparison-Rules.html#GUID-98BE3A78-6E33-4181-B5CB-D96FD9DC1694

    展开全文
  • C++类型转换主要分为两种:隐式类型转换和显式类型转换(强制类型转换)。 1 (type)expression //C风格转换格式 2 static_cast<type>(expression) //C++风格转换格式 1. 隐式类型转换 所谓隐式类型转换,是指...

    C++类型转换

    C++类型转换主要分为两种:隐式类型转换和显式类型转换(强制类型转换)。

    (type)expression //C风格转换格式
    static_cast<type>(expression) //C++风格转换格式
    

    1. 隐式类型转换

    所谓隐式类型转换,是指不需要用户干预,编译器默认进行的类型转换行为(很多时候用户可能都不知道到底进行了哪些转换)。

    隐式类型转换一般分为两种:内置数据类型、自定义数据类型。

    1.1 内置数据类型

    C++的隐式类型转换,都满足一个基本原则:由低精度向高精度的转换。若不满足该原则,编译器会提示编译警告

    举例说明:
    例1:混合类型的算术运算表达式中

    int int_value = 8;
    double dou_value = 10.7;
    double dou_Sum = int_value + dou_value; // int_value会被自动转换为double类型,用转换的结果再与dou_value相加.
    

    例2:不同类型的赋值操作时

    int value = true; // bool类型被转换为int类型
    

    例3:函数参数传值时

    void func(double dArg); // 声明函数
    func(1); // 调用函数。整型数值1被默认转换为double类型数值1.0
    

    例4:函数返回值时

    double add(int num1, int num2)
    {
       return (num1 + num2); // 运算结果会被隐式转换为double类型返回
    }
    

    若不满足该原则,编译器会提示编译警告。如下:

    double num1 = 100.66;
    int num2 = num1; // : warning C4244: “初始化”:从“double”转换到“int”,可能丢失数据
    

    如果我们不想看到警告,可以选择强制类型转换。如下:

    double num1 = 100.66;
    int num2 = (int)num1;
    
    1.2 自定义数据类型

    隐式类型转换的风险一般存在于自定义类型转换间。尤其需要注意自定义类的构造函数。例如:

     class MyString
    {
    public:
        MyString(int n) {}; // 本意:预先分配n个字节给字符串
        MyString(const char* p) {}; // 用C风格的字符串p作为初始化值 
        // ......
    };
    
    void main()
    {
        MyString s1 = "China"; //OK 隐式转换,等价于MyString s1 = MyString(”China”) 
        MyString s2(10); // OK 分配10个字节的空字符串
        MyString s3 = MyString(10); // OK 分配10个字节的空字符串
    
        MyString s4 = 10; // OK,编译通过。也是分配10个字节的空字符串
        MyString s5 = 'A'; // 编译通过。分配int('A')个字节的空字符串
        // s4 和s5 分别把一个int型和char型,隐式转换成了分配若干字节的空字符串,容易令人误解。
    }
    

    如上例,要想禁止此种隐式类型转换,可以使用C++关键字explicit。

    2. 强制类型转换

    C++为了规范C中的类型转换,加强类型转换的可视性,引入了四种强制类型转换操作符:static_cast, reinterpret_cast,const_cast和dynamic_cast,他们本质上都是模板类。
    C++风格类型转换应用场景

    2.1 static_cast

    它用于非多态类型的转换(静态转换),对应于C中的隐式类型转换,但不能用于两个不相关类型的转换,如整形和整形指针之间的转换,虽然二者都是四个字节,但他们一个表示数据,一个表示地址,类型不相关,无法进行转换。

    该转换在编译时完成,和C风格的类型转换相似,不过要注意下面几点:

    (1)不能在没有派生关系的两个类类型之间转换;

    (2)不能去除掉原有类型的类型修饰符,例如const,volatile,__unaligned;

    (3)转换对象时由于没有动态类型检查,所以由基类对象转换成派生类对象的时候存在安全隐患

    2.2 reinterpret_cast

    有着与C风格的强制转换同样的能力。

    它可以转化任何内置的数据类型为其他任何的数据类型,也可以转化任何指针类型为其他的类型。

    它甚至可以转化内置的数据类型为指针,无须考虑类型安全或者常量的情形。不到万不得已绝对不用。

    2.3 const_cast

    (1)常量指针 被强转为 非常量指针,且仍然指向原来的对象;

    (2)常量引用 被强转为 非常量引用,且仍然指向原来的对象;

    (3)常量对象 被强转为 非常量对象。

    2.4 dynamic_cast

    (1)其他三种都是编译时完成的。dynamic_cast是运行时处理的,运行时要进行类型检查

    (2)不能用于内置基本数据类型间的强制转换。例如:

    double dValue = 12.12;
    int nDValue = dynamic_cast<int>(dValue); // error C2680 : “int” : dynamic_cast 的目标类型无效。目标类型必须是指向已定义类的指针或引用
    

    (3)使用dynamic_cast进行转换时,基类中一定要有虚函数,否则编译不通过。

    需要有虚函数的原因:类中存在虚函数,就说明它有想要让基类指针或引用指向派生类对象的必要,此时转换才有意义。

    由于运行时类型检查需要运行时类型信息,而这个信息存储在类的虚函数表中,只有定义了虚函数的类才有虚函数表。

    class A
    {};
    
    class B : public A
    {};
    
    class C
    {};
    
    void main()
    {
        A *pA = new A;
        B *pB = dynamic_cast<B*>(pA); // 编译错误error C2683: “dynamic_cast”:“A”不是多态类型
    }
    

    (4)dynamic_cast转换若成功,返回的是指向类的指针或引用;若失败则会返回NULL。

    (5)在类的转换时,在类层次间进行上行转换(upcast)时,dynamic_cast和static_cast的效果是一样的

    在进行下行(downcast)转换时,dynamic_cast具有类型检查的功能,比static_cast更安全。

    向上转换即为指向子类对象的向上转换,即将子类指针转化父类指针

    向下转换的成败取决于将要转换的类型,即要强制转换的指针所指向的对象实际类型与将要转换后的类型一定要相同,否则转换失败。

    关于(4)、(5)两条的代码示例如下:

    #include <iostream> 
    #include <cstring>
    using namespace std;
    
    class A
    {
    public:
        virtual void f()
        {
            cout << "A::f()" << endl;
        }
    };
    
    class B : public A
    {
    public:
        void f()
        {
            cout << "B::f()" << endl;
        }
    
        void bf()
        {
            cout << "B::bf()" << endl;
        }
    };
    
    class C
    {
        void pp()
        {
            return;
        }
    };
    
    int fun()
    {
        return 1;
    }
    
    void main()
    {
        A* pAB = new B; // pAB是A类型的指针指向一个B类型的对象
        A* pAA = new A; // pAA是A类型的指针指向一个A类型的对象
        B* pB = nullptr;
        C* pC = nullptr;
        pB = dynamic_cast<B*>(pAB); // 结果为not nullptr,向下转换成功,pAB指向的就是B类型的对象,所以可以转换成B类型的指针。 
        if (nullptr == pB)
        {
            cout << "dynamic_cast :: nullptr" << endl;
        }
        else
        {
            cout << "dynamic_cast :: not nullptr" << endl;
        }
        // 等价于static_cast
        pB = static_cast<B*>(pAB); // 结果为not nullptr,向下转换成功,pAB指向的就是B类型的对象,所以可以转换成B类型的指针。 
        if (nullptr == pB)
        {
            cout << "static_cast :: nullptr" << endl;
        }
        else
        {
            cout << "static_cast :: not nullptr" << endl;
        }
    
        pB = dynamic_cast<B*>(pAA); // 结果为nullptr,向下转换失败。pAA指向的是A类型的对象,所以无法转换为B类型的指针。
        if (nullptr == pB)
        {
            cout << "dynamic_cast :: nullptr" << endl;
        }
        else
        {
            cout << "dynamic_cast :: not nullptr" << endl;
        }
    
        // static_cast的不安全性测试
        pB = static_cast<B*>(pAA); // 结果为not nullptr,向下转换成功。pAA指向的是A类型的对象,竟然转换为B类型的指针!
        if (nullptr == pB)
        {
            cout << "static_cast :: nullptr" << endl;
        }
        else
        {
            cout << "static_cast :: not nullptr" << endl; // 不安全性
            pB->f();  // A::f()
            pB->bf();  // B::bf()
        }
    
        pC = dynamic_cast<C*>(pAB); // 结果为nullptr,向下转换失败。pAB指向的是B类型的对象,所以无法转换为C类型的指针。
        if (nullptr == pC)
        {
            cout << "dynamic_cast :: nullptr" << endl;
        }
        else
        {
            cout << "dynamic_cast :: not nullptr" << endl;
        }
    
    //  pC = static_cast<C*>(pAB); 
    //  error C2440: “static_cast”: 无法从“A *”转换为“C *” 与指向的类型无关;转换要求 reinterpret_cast、C 样式转换或函数样式转换
    
        delete pAB;
        delete pAA;
        
        system("pause");
    }
    // run out:
    /*
    dynamic_cast :: not nullptr
    static_cast :: not nullptr
    dynamic_cast :: nullptr
    static_cast :: not nullptr
    A::f()
    B::bf()
    dynamic_cast :: nullptr
    */
    

    由程序运行结果分析:static_cast的不安全性显而易见

    pB = static_cast<B*>(pAA); 
    

    向下转换结果为not nullptr。pAA指向的是A类型的对象,竟然可以转换为B类型的指针!相当危险!

    (6)使用dynamic_cast的类型转换,其转换结果几乎都是执行期定义(implementation-defined)。因此,使用reinterpret_casts的代码很难移植。

    参考博客

    C++类型转换

    PS:小米面试问到了关于C++类型转换,特此学习一下~~

    机会总是留给有准备的人,加油!

    展开全文
  • 如果把通过函数或方法调用,明确的将某种类型转换成另一种类型称为显示转换 ,相反则称为隐式类型转换 。google和维基百科中没有找到“显示类型转换”,“隐式类型转换”的字眼。暂且这么称呼。 一、 运算中存在的...
  • 一、隐式类型转换 隐式类型转换也叫做自动类型转换。 1、规则: 从存储范围小的类型到存储范围大的类型。 2、转换方向: byte→short(char)→int→long→float→double(这里指的是只有前面的数据类型能随便转换成...
  • JavaScript隐式类型转换

    2020-11-24 11:49:12
    之所以不同的数据类型之间可以做运算,是因为JavaScript引擎在运算之前会悄悄的把他们进行了隐式类型转换的,如下是数值类型和布尔类型的相加: 复制代码 代码如下: 3 + true; // 4 结果是一个数值型!如果是在C...
  • js隐式类型转换

    千次阅读 2019-01-21 10:10:55
    你所忽略的js隐式转换 你有没有在面试中遇到特别奇葩的js隐形转换的面试题,第一反应是怎么会是这样呢?难以自信,js到底是怎么去计算得到结果,你是否有深入去了解其原理呢?下面将深入讲解其实现原理。 其实这篇...
  • 本篇文章根据《你不知道的javascript 中卷》及ECMAScript标准总结而来,如有错误还请指正。...如果对象有能力被转换为不止一种原语类型,可以使用可选的期望类型来暗示那个类型 以上是ECMAScri...
  • 主要介绍了简单介绍JavaScript数据类型之隐式类型转换的相关资料,需要的朋友可以参考下
  • C语言隐式类型转换规则。了解一下对写程序有好处,可以防止不必要的错误
  • c++ 隐式类型转换

    千次阅读 多人点赞 2018-12-25 17:14:32
    文章目录谈谈c++隐式类型转换列举一些隐式类型转换的例子有时候隐式类型转换并不好explic关键词的用法总结 谈谈c++隐式类型转换 什么是c++隐式类型转换?这是指c++自动将一种类型转换成另一种类型,是编译器的一种...
  • C++的隐式类型转换

    2020-12-22 23:18:38
     废话完后,讲讲自己捡到的石头:隐式类型转换  学习出处:《Effective C++》 lostmouse大人翻译 class TestInt { public: int GetData()const{ return i;}; TestInt(int ii):i(ii){}; //构造函数 private...
  • 学习隐式类型转换和强制类型转换的基本概念. 本意或非本意下使用类型转换时可能会出现的问题. 在C语言是可以进行类型之间的转换且其中存在两种类型转换的方式 强制类型转换 隐式类型转换 强制类型转换 强制类型...
  • 隐式类型转换规则

    千次阅读 2019-06-03 21:05:45
    在js中,当运算符在运算时,如果两边数据不统一,CPU就无法计算,这时我们编译器会自动将运算符两边的数据做一个数据类型转换,转成一样的数据类型再计算 这种无需程序员手动转换,而由编译器自动转换的方式就称为...
  • 显示类型转换和隐式类型转换

    千次阅读 2019-04-28 17:26:37
    显示类型转换 1.Number():函数把对象的值转换为数字,如果对象的值无法转换为数字,那么 Number() 函数返回 NaN。 var a = 'true'; console.log(typeof(Number(a)) + '-' + Number(a)); // number-NaN var ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 196,281
精华内容 78,512
关键字:

隐式类型转换

友情链接: project.zip