c++隐式类型转换存在的陷阱
目录
- 目标代码
- 构造函数定义的隐式类型转换
- 分析a1
- 分析a2
- 分析a3
目标代码 旨在弄懂下面的代码,明确变量a1,a2,a3在创建时编译器究竟干了那些事:
#include
using namespace std;
class A{
public:
int x;
A() {cout<<"A()"<
运行结果:
文章图片
构造函数定义的隐式类型转换 任何只接受一个参数的构造函数,都隐式地定义了由该参数向该类型的隐式类型转换
如
A(int i)
定义了一个由int向A的隐式类型转换所以,在任何使用A对象的地方,可以用一个int代替,此时,int会转换为一个A类型临时变量
如对a1变量的赋值操作:
A a1;
//声明a1,a1被默认初始化
a1 = 2;
//2转换为A类型的临时变量,对a1进行赋值操作
对于隐式类型转换,需要注意两点:
- 隐式类型转换只允许一步转换
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; }
- 接受隐式类型转换得到的对象的函数,参数传递方式必须是const引用传递
因为c++中,一般不修改临时对象,所以临时对象只能传递给const引用。分析a1
A a1
:a1进行默认初始化,调用默认构造函数
A()
a1 = 2
- 字面量2隐式转换为A类型的临时对象
- 该临时对象通过拷贝运算符
operator=
拷贝给a1 - 因为是临时对象,所以
operator=
必须接受const引用,否则造成编译错误
A a2 = 2
- 字面量2隐式转换为A类型的临时对象
- 用临时对象来拷贝初始化a2,调用拷贝构造函数
A(const A&)
,相当于A a2(A(2))
- 因为是临时对象,所以拷贝构造函数
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 【c++隐式类型转换存在的陷阱】用a1直接初始化a3,调用
A(const A&)
推荐阅读
- 命令行与C++
- 详解PostgreSQL数据类型
- C++中菱形继承的解释与处理详解
- java|java mybatis如何操作postgresql array数组类型
- C++|C++ Primer的变量和基本类型详解
- 打造自己的JavaScript工具库(1.|打造自己的JavaScript工具库(1. 数据类型校验)
- 《C++要笑着学》|【C++要笑着学】认识C++ | C++的发展史 | 学习方法建议
- 《C++要笑着学》|【C++要笑着学】缺省参数 | 函数重载
- 《C++要笑着学》|【C++要笑着学】内联函数 | 关键字auto | 范围for | 关键字 nullptr
- C/C++编程(libcurl学习(linux + cmake))