补充:操作符
对自定义的类型转换保持警觉
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
和delete
new
操作符是由语言内建的,不能被改变意义。它复杂(1)分配足够的内存,然后(2)调用一个构造函数给对象设定初值。
delete
操作符会先(1)调用析构函数,然后(2)释放内存。
operator new
和operator delete
函数operator new
和new
操作符不一样,不负责调用构造函数。函数声明为void* operator new(size_t size);
。其返回值类型是void*
。此函数返回一个指针,指向一块原始的,未设初值的内存。和malloc一样,它的唯一任务就是分配内存。
函数operator delete
与之对应。函数声明为void operator delete(void* xxx);
。不会调用析构函数。
- Placement new
有时有一些分配好的内存需要在上面构建对象,placement new允许你那么做。
调用方式:new (buffer) Widget();
如果使用 placement new 在某内存块产生对象,你应该避免对那块内存使用delete
操作符。为了抵消该对象的构造函数影响,你应该直接调用对象析构函数。
- 数组
CRE:数组版的new
操作符针对数组中每个对象调用一个构造函数。对应地,数组版的delete
操作符针对数组中每个元素调用析构函数然后再释放内存。
CRE:数组版的operator new[]
和operator delete[]
是很晚才加入C++的一个特性。
(END)