目标代码

旨在弄懂下面的代码,明确变量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. 微服务架构 | 3.1 Netflix Eureka 注册中心

    目录 前言 1. Eureka 基础知识 1.1 Eureka 模型中的服务器与客户端 1.2 Eureka 的 30s 启动机制 1.3 Eureka 为什么注册服务的 IP ,而不是主机名 1.4 ...

  2. Web开发之Servlet

    当一个请求到达服务端,服务器怎么处理? 当一个请求到达服务端时,由服务端的引擎来进行分析.它根据工程名找到工程, 然后拿到URL的资源地址和web.XML文件的所有的进行对比,和哪一个对比上就找到了具 ...

  3. 开源数据可视化BI工具SuperSet(安装)

    本次安装教程共分两大步骤,因为Superset 基于python3编写的web应用(flask) 所以要求python3环境,故首先要将linux系统自带的环境进行升级,已经是python3的可跳过- ...

  4. 《剑指offer》面试题16. 数值的整数次方

    问题描述 实现函数double Power(double base, int exponent),求base的exponent次方.不得使用库函数,同时不需要考虑大数问题. 示例 1: 输入: 2.0 ...

  5. Jquery操作文本内容(三个方法:html()、text()、var())

    Jquery操作文本内容(三个方法:html().text().var()) 一.html()获取和设置文本内容和标签 1.获取标签里的结构和内容 $("ul").html() / ...

  6. 系统信号SIGHUP、SIGQUIT、SIGTERM、SIGINT的场景

    SIGHUP:hong up 挂断.本信号在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控制进程结束时, 通知同一session内的各个作业, 这时它们与控制终端不再关联.登录Linux时 ...

  7. Java 实现订单未支付超时自动取消

    在电商上购买商品后,如果在下单而又没有支付的情况下,一般提示30分钟完成支付,否则订单自动.比如在京东下单为完成支付: 超过24小时,就会自动取消订单,下面使用 Java 定时器实现超时取消订单功能. ...

  8. pytorch运行错误:ValueError: too many dimensions 'str'

    问题: 本人在使用BERT进行微调的时候,在读取数据的时候出现了一个错误:ValueError: too many dimensions 'str'    于是我Debug了以后,发现问题出现在这个部 ...

  9. k8s基本概念,资源对象

    kubernetes里的master指的是集群控制节点 master负责是整个集群的管理和控制 kubernetes3大进程 API server 增删改查操作的关键入口 controller man ...

  10. JAVA多线程学习十五 - 阻塞队列应用

    一.类相关属性 接口BlockingQueue<E>定义: public interface BlockingQueue<E> extends Queue<E> { ...