目标代码

旨在弄懂下面的代码,明确变量a1,a2,a3在创建时编译器究竟干了那些事:

#include<iostream>
using namespace std; class A{
public:
int x;
A() {cout<<"A()"<<endl;}
A(int i) : x(i){cout<<"A(int i)"<<endl;}
A(const A &ra) : x(ra.x)
{cout<<"A(const A&)"<<endl;}
void operator=(const A&){cout<<"operator="<<endl;}
};
int main(){
cout<<"the assignment of a1 : "<<endl;
A a1;
a1 = 2;
cout<<"the copy initialization of a2 : "<<endl;
A a2 = 2;
cout<<"the direct initialization of a3 :"<<endl;
A a3(a1);
return 0;
}

运行结果:

构造函数定义的隐式类型转换

任何只接受一个参数的构造函数,都隐式地定义了由该参数向该类型的隐式类型转换

A(int i)定义了一个由int向A的隐式类型转换

所以,在任何使用A对象的地方,可以用一个int代替,此时,int会转换为一个A类型临时变量

如对a1变量的赋值操作:

A a1;   //声明a1,a1被默认初始化
a1 = 2; //2转换为A类型的临时变量,对a1进行赋值操作

对于隐式类型转换,需要注意两点:

  1. 隐式类型转换只允许一步转换

    class B{
    public:
    string B_s;
    B() = default;
    B(string s) : B_s(s){};
    };
    int main(){
    B b1,b2;
    //错误:char*->string->B,进行了两步转换
    b1 = "hello";
    b2 = string("hello");
    return 0;
    }
  2. 接受隐式类型转换得到的对象的函数,参数传递方式必须是const引用传递

因为c++中,一般不修改临时对象,所以临时对象只能传递给const引用

分析a1

A a1:

a1进行默认初始化,调用默认构造函数A()

a1 = 2

  1. 字面量2隐式转换为A类型的临时对象
  2. 该临时对象通过拷贝运算符operator=拷贝给a1
  3. 因为是临时对象,所以operator=必须接受const引用,否则造成编译错误

分析a2

A a2 = 2

  1. 字面量2隐式转换为A类型的临时对象
  2. 用临时对象来拷贝初始化a2,调用拷贝构造函数A(const A&),相当于A a2(A(2))
  3. 因为是临时对象,所以拷贝构造函数A(const A&)必须接受const引用,否则造成编译错误

特别注意

编译器会将A a2(A(2))优化为A a2(2)

所以程序输出“A(int i)”,而不是“A(const A&)”

但是底层仍然调用了A(const A&),所以如果把A(const A&)改为A(A&),会造成编译错误 error: cannot bind non-const lvalue reference of type 'A&' to an rvalue of type 'A'

这提示我们,在编写c++程序时,如果不改变对象的值,那么习惯性地采用const引用会避免许多难解的编译错误

分析a3

用a1直接初始化a3,调用A(const A&)

c++隐式类型转换存在的陷阱的更多相关文章

  1. js条件判断时隐式类型转换

    Javascript 中,数字 0 为假,非0 均为真 在条件判断运算 == 中的转换规则是这样的: 如果比较的两者中有布尔值(Boolean),会把 Boolean 先转换为对应的 Number,即 ...

  2. dynamic_cast 和 static_cast 隐式类型转换的区别

    首先回顾一下C++类型转换: C++类型转换分为:隐式类型转换和显式类型转换 第1部分. 隐式类型转换 又称为“标准转换”,包括以下几种情况:1) 算术转换(Arithmetic conversion ...

  3. c++ operator操作符的两种用法:重载和隐式类型转换,string转其他基本数据类型的简洁实现string_cast

    C++中的operator主要有两个作用,一是操作符的重载,一是自定义对象类型的隐式转换.对于操作符的重载,许多人都不陌生,但是估计不少人都不太熟悉operator的第二种用法,即自定义对象类型的隐式 ...

  4. C++的隐式类型转换与转换操作符

    C++标准允许隐式类型转换,即对特定的类,在特定条件下,某些参数或变量将隐形转换成类对象(创建临时对象).如果这种转换代价很大(调用类的构造函数),隐式转换将影响性能.隐式转换的发生条件:函数调用中, ...

  5. C++的隐式类型转换

    C++是一种复杂的语言,其中有许多“好玩”的特性,学习C++的过程就像在海边捡一颗颗石头,只要坚持不懈,也许一颗颗小石头也能建起你自己小小的城堡. 废话完后,讲讲自己捡到的石头:隐式类型转换 学习出处 ...

  6. 「译」JavaScript 的怪癖 1:隐式类型转换

    原文:JavaScript quirk 1: implicit conversion of values 译文:「译」JavaScript 的怪癖 1:隐式类型转换 译者:justjavac 零:提要 ...

  7. 【M21】利用重载技术避免隐式类型转换

    1.考虑UPint 的加法+,UPint a, b, result; 为了使result = a+10; result= 10+a; 都能通过编译,操作符重载如下: const UPint opera ...

  8. JS--显示类型转换Number—隐式类型转换

    显示类型转换 (强制类型转换):Number()parseInt()parseFloat() Number是整体转换--能够把一个看起来像数字的字符串转成数字--尽量去转换能转的都转了 var a = ...

  9. Mysql隐式类型转换原则

    MySQL 的隐式类型转换原则: - 两个参数至少有一个是 NULL 时,比较的结果也是 NULL,例外是使用 <=> 对两个 NULL 做比较时会返回 1,这两种情况都不需要做类型转换 ...

随机推荐

  1. 【Java】Eclipse常用快捷键

    Eclipse常用快捷键 * 1.补全代码的声明:alt + / * 2.快速修复: ctrl + 1 * 3.批量导包:ctrl + shift + o * 4.使用单行注释:ctrl + / * ...

  2. MCU软件最佳实践——独立按键

    1. 引子 在进行mcu驱动和应用开发时,经常会遇到独立按键驱动的开发,独立按键似乎是每一个嵌入式工程师的入门必修课.笔者翻阅了许多书籍(包括上大学时候用的书籍)同时查阅了网上许多网友的博客,无一例外 ...

  3. Android官方文档翻译 十二 3.Supporting Different Devices

    Supporting Different Devices 支持不同设备 Dependencies and prerequisites 依赖关系和先决条件 Android 1.6 or higher A ...

  4. 达索CATIA许可证(License)管理使用和优化

    现下主流的V6版本CATIA,是由达索公司提供授权的浮动型License,其客户端通过企业内网从许可证服务器获得许可证,最少要有一个服务器端DS License Server提供一定数量的Licens ...

  5. Vulnhub - THE PLANETS: EARTH

    环境配置 从www.vulnhub.com下载靶机,在VMware中导入,自动分配IP 主机发现 通过对内网主机的扫描,VMware为目标主机 端口扫描 使用nmap对主机进行扫描 发现443端口信息 ...

  6. web刷题记录 极客大挑战2019Knife upload buy a flag

    极客2019Knife webshell就是以asp.php.jsp或者cgi等网页文件形式存在的一种代码执行环境,主要用于网站管理.服务器管理.权限管理等操作.使用方法简单,只需上传一个代码文件,通 ...

  7. 【小记录】android下opencv的cv::dft()函数,CPU版本与opencl版本的性能相差16倍

            cv::dft  相差15.9倍         cpu版本  单次调用  0.029448 毫秒         opencl版本  单次调用  0.468688  毫秒   差别仅 ...

  8. 初识WorldWind——WorldWind编译生成,解决乱码等问题

    本文中World Wind的GitHub源码下载地址:https://github.com/hujiulin/WorldWind 美国国家航空航天局(National Aeronautics and ...

  9. pytest文档3-测试用例setup和teardown

    用例运行级别 模块级(setup_module/teardown_module)开始于模块始末,全局的 函数级(setup_function/teardown_function)只对函数用例生效(不在 ...

  10. [WAF攻防]从WAF攻防角度重看sql注入

    从WAF攻防角度重看sql注入 攻防都是在对抗中逐步提升的,所以如果想攻,且攻得明白,就必须对防有深刻的了解 sql注入的大体流程 Fuzz测试找到注入点 对注入点进行过滤检测,及WAF绕过 构建pa ...