《C++ Primer plus》中的类型转换与临时变量

类型转换

内置类型转换

将一个标准类型变量的值赋给另一种标准类型的变量时,如果这两种类型兼容,则C++自动将这个值转换为接收变量的类型,虽然在某些情况下可能导致精度的降低。

C++不自动转换不兼容的类型,如无法将整型自动转换为指针类型,但在不考虑是否有意义的情况下,这可以通过强制类型转换实现,例如:

int * p = (int *) 10;

函数参数按值传递时,编译器依据函数原型对使用的参数类型是否正确进行检查,如果不正确,在可能的情况下将会发生类型转换。

类类型转换

从其他类型到类类型

只接受一个参数的构造函数(或接受多个参数的构造函数但仅第一个参数未提供默认值),可以作为自动类型转换函数,实现隐式类型转换,如对于构造函数:

Stonewt(double lbs); // 或Stonewt(int stn, double lbs = 0);

可以编写如下代码:

Stonewt myCat;
myCat = 19.6;

实现了从double到类类型Stonewt的自动类型转换。

但这种自动特性可通过关键字explicit关闭:

explicit Stonewt(double lbs);

关闭自动类型转换后仍允许强制显式类型转换。

从类类型到其他类型

构造函数仅可用于从某种类型到类类型的转换,要进行相反的转换,则需要定义转换函数:

operator typeName();

临时变量

函数生成临时变量

函数参数按值传递时,形参得到的实际上是实参的副本,而非原来的数据。

函数参数按引用传递时,当实参的类型正确但不是左值以及实参的类型不正确但可转换为正确的类型时,形参是const引用的函数将会生成临时变量,因为const引用意味着函数不会改变参数值,而生成临时变量这种类似于按值传递的行为正好符合不改变参数值的要求。以非const引用作为形参的函数则无法接受类型正确的非左值或类型不正确的实参。

类初始化生成临时变量

使用构造函数但并不初始化新对象,而是为已经存在的对象赋值时,构造函数将会创建一个新的、临时的对象,然后其内容被复制给已存在的对象来实现赋值,随即析构函数被调用,删除此临时对象。总之,在上述的赋值语句中使用构造函数总会导致在赋值前创建一个临时对象。如果既可以通过初始化,也可以通过赋值来设置对象的值,则应采用初始化方式。通常这种方式的效率更高。

而在初始化新对象(注意,不是常规的赋值)以及按值传递参数或返回对象时,类的复制构造函数被调用,因为按值传递意味着创建原始变量的副本。此外,编译器生成临时对象,也将使用复制构造函数。

将已有的对象赋给另一个对象时,将使用重载的赋值运算符。而对于新创建的对象使用赋值来进行初始化,可能分两步实现,即使用复制构造函数创建一个临时对象,然后通过赋值将临时对象的值复制到新对象中;也可能使用复制构造函数直接创建新对象,这取决于具体的实现。

如果方法或函数返回局部对象,则应返回对象,而不是指向对象的引用。在这种情况下,将使用复制构造函数来生成返回的对象,同时需要考虑是否返回const对象以避免返回值成为可修改的左值,防止类似于重载+运算符有“force1+force2=net”这种令人迷惑的现象出现。如果方法或函数要返回一个没有公有复制构造函数的类的对象,那么只能返回一个指向这种对象的引用,重载<<运算符中ostream类的cout对象就是一个很好的例子。在返回对象和对象的引用均可时,应首选效率更高的引用。

posted @ 2021-08-15 15:34  溪嘉嘉  阅读(220)  评论(0编辑  收藏  举报