• c++隐式类型转换存在的陷阱


    1|0目标代码

    旨在弄懂下面的代码,明确变量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; }

    运行结果:

    image-20220228223902552

    2|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引用

    3|0分析a1

    A a1:

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

    a1 = 2

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

    4|0分析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引用会避免许多难解的编译错误

    5|0分析a3

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


    __EOF__

    本文作者萌之上
    本文链接https://www.cnblogs.com/timothy020/p/15948051.html
    关于博主:评论和私信会在第一时间回复。或者直接私信我。
    版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
    声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
  • 相关阅读:
    Leetcode链表问题汇总
    [计算机网络实验] ICMPv4协议
    Go Context包
    遍历map的4种方法
    @MapperScan 和 @Mapper 源码走读
    基于JAVA企业公开招聘系统计算机毕业设计源码+系统+mysql数据库+lw文档+部署
    相对位置编码之RPR式:《Self-Attention with Relative Position Representations》论文笔记
    京东API接口(商品详情页采集+关键词搜索商品列表):开启电商业务的新篇章
    深入探索Spring Boot的自动配置机制
    linux crontab: ip: command not found
  • 原文地址:https://www.cnblogs.com/timothy020/p/15948051.html