写这篇博文之前在纠结是直接先跳到oo去,还是继续保持顺序读下去?
很有可能读完oo部分就不会回来耐心地读这些章节了,所以还是继续吧,提高效率。
P217:
输入输出标准库(IO library)分别重载了位操作符>>和<<用于输入和输出。即使很多程序员从未直接使用过位操作符,但是相当多的程序都大量用到这些操作符在IO标准库中的重载版本。
P224:
由于后自增操作的优先级高于解引用操作,因此*iter++等效于*(iter++)。
建议:简洁即是美
有经验的C++程序眼非常重视简练,他们更喜欢这样写:
cout << *iter++ << end;
而不采用下面这种冗长的等效代码:
cout << *iter << endl;
++iter;
要不断地研究类似的代码,最后达到一目了然的地步。
注:变聪明一点才可以,注意平时的积累。
P229:
因为sizeof返回整个数组在内存中的存储长度,所以用sizeof数组结果除以sizeof其元素类型的结果,即可求出数组元素的个数:
// sizeof(ia)/sizeof(*ia) returns the number of elements in ia
int sz = sizeof(ia) / sizeof(*ia);
P204:
删除指针后,该指针变成悬垂指针。悬垂指针指向曾经存放对象的内存,但该对象已经不再存在了。
一旦删除了指针所指向的对象,立即将指针置为0,这样就非常清楚地表明指针不再指向任何对象。
注:这是一个好习惯。
P243:
警告:动态内存的管理容易出错
与动态内存分配相关的三种常见的错误:
1. 删除(delete)指向动态分配内存的指针失败,因而无法将该内存返还给自由存储区。删除动态分配内存失败称为“内存泄露(memory leak)”。内存泄露很难发现,一般需要等应用程序运行一段时间后,耗尽了所有内存空间时,内存泄露才会显露。
2. 读写已删除的对象。
3. 对同一内存空间使用两侧delete表达式。
注:这就是为啥强调要使用智能指针的原因吧。
P250:
显示转换也称为强制类型转换(cast),包括下列名字命名的强制类型转换操作符:static_cast、dynamic_cast、const_cast和reinterpret_cast。
注:这几个看着熟悉其实陌生的名字,多少次折磨过我的神经。读这一章把这几个名字弄明白了也算没有白读。
P251
!!!何时需要强制类型转换
因为要覆盖通常的标准转换,所以需要显式使用强制类型转换。
double dval;
int ival;
ival *= dval; // ival = ival * dval
为了与dval做乘法操作,需将ival转换为double型,然后将乘法操作的double型结果截尾为int型,再赋值给ival。为了去掉将ival转换为double型这个不必要的转换,可通过如下强制将dval转换为int型:
ival *= static_cast<int>(dval); // converts dval to int
显式使用强制类型转换的另一个原因是:可能存在多种转换时,需要选择一种特定的类型转换。
注:新技能get√
P251:
命名的强制类型转换
dynamic_cast:
支持运行时识别指针或引用所指向的对象。第18.2节中将讨论。
cosnt_cast:
将转换掉表达式的const性质。
只有使用const_cast才能将const性质转换掉。
static_cast:
编译器隐式执行的任何类型转换都可以由static_cast显示完成:
double d = 97.0;
// cast specified to indicate that the conversion is intentional
char ch = static_cast<char>(d);
当需要将一个较大的算术类型赋值给较小的类型时,使用强制转换非常有用。对于从一个较大的算术类型到一个较小类型的赋值,编译器通常会产生警告。当我们显式地提供强制类型转换时,警告信息就会被关闭。
void* p = &d; // ok:address of any data object can be stored in a void*
// ok:converts void* back to the original pointer type
double *dp = static_cast<double*>(p);
可通过static_cast将存放在void*中的指针值强制转换为原来的指针类型。
reinterpret_cast:
通常为操作数的位模式提供较低层次的重新解释。
建议:避免使用强制类型转换
强制类型转换关闭或挂起了正常的类型检查,强烈建议程序员避免使用强制类型转换,不依赖强制类型转换也能写出很好的C++程序。
设计合理的系统应不需要使用强制转换抛弃const特性。static_cast和dynamic_cast各有各的用途,但都不应频繁使用。
注:好不容易把看起来高大上的dynamic_cast,static_cast之类看完,结果来一句尽量避免使用,好吧,养成好习惯。
P254:
旧式强制类型转换
引入命名的强制类型转换操作符之前,显示强制转换用圆括号将类型括起来实现:
char *pc = (cha *)ip;
效果与reinterpret_cast符号相同,但可视性较差,难以跟踪错误的转换。
标准C++为了增强可视性,引入命名的强制转换操作符。虽然标准C++仍支持旧式强制转换符号,但是我们建议,只有在C语言或标准C++之前的编译器上编写代码时,才使用这种语法。
例如,我们可用旧式符号实现强制转换:
int ival; double dval;
ival += int(dval); // static_cast: converts double to int
const char* pc_str;
string_copy((char*)pc_str); // const_cast: casts away const
int* ip;
char* pc = (char *)ip; // reinterpret_cast: treats int* as char*
注:原来我的很多习惯还停留在在C语言和标准C++之前呀。
第五章 表达式(完)