zhouqijie

补充:操作符

对自定义的类型转换保持警觉

GPT:当类中定义了自定义的类型转换函数时,这些函数可以让对象隐式地转换到其他类型。这种隐式转换很容易在不显眼的地方发生,导致难以追踪的错误。
GPT:隐式类型转换可能使代码读者难以理解一个表达式的真正意图,因为转换过程不是显而易见的。这会增加代码的复杂性和理解成本。

对于定制的类型转换函数要非常谨慎,最好是避免它们的使用。如果必须要使用,推荐明确地标记为explicit,这样就能防止编译器自动进行这种类型转换,从而避免上述问题。使用explicit关键字可以确保类型转换是明确和可控的,减少不必要的错误和混淆。

区别increment/decrement操作符的前置/后置形式

前置式意义”increment and fetch”(累加然后取出),后置式意义”fetch and increment”。

后置式需要产生一个临时对象,作为返回值之用。前置式就没有如此的临时对象。处理用户自定义类型时,应该尽可能使用前置式,因为天生体质较佳。

MyObj& operator++();//前置式    
const MyObj operator++(int);//后置式    
//后置式increment操作符会返回一个对象代表旧值。这个对象是const的。    
//所以i++++无法通过编译。(因为本质语义是错误的)    
//为了确保前置式和后置式的行为一致,应该以前置式为基础,这样就只需要维护前置式版本。    

GPT:在for循环中使用迭代变量i,如果涉及到更复杂的类型特别是对象时,使用++i可能更优,因为i++可能会涉及到临时对象的创建。对于基本数据类型,这一点不成问题,但如果循环变量是一个迭代器或复杂类的实例,使用++i可以避免潜在的额外开销。

千万不要重载&&||,操作符

重载&&||会使短路行为失效。

重载,难以保证其行为像它应该有的那样。

了解各种不同意义的new和delete

new操作符是由语言内建的,不能被改变意义。它复杂(1)分配足够的内存,然后(2)调用一个构造函数给对象设定初值。
delete操作符会先(1)调用析构函数,然后(2)释放内存。

函数operator newnew操作符不一样,不负责调用构造函数。函数声明为void* operator new(size_t size);。其返回值类型是void*。此函数返回一个指针,指向一块原始的,未设初值的内存。和malloc一样,它的唯一任务就是分配内存。

函数operator delete与之对应。函数声明为void operator delete(void* xxx);。不会调用析构函数。

有时有一些分配好的内存需要在上面构建对象,placement new允许你那么做。

调用方式:new (buffer) Widget();

如果使用 placement new 在某内存块产生对象,你应该避免对那块内存使用delete操作符。为了抵消该对象的构造函数影响,你应该直接调用对象析构函数。

CRE:数组版的new操作符针对数组中每个对象调用一个构造函数。对应地,数组版的delete操作符针对数组中每个元素调用析构函数然后再释放内存。

CRE:数组版的operator new[]operator delete[]是很晚才加入C++的一个特性。

(END)