《More Effective C++ 35个改善编程与设计的有效方法》——第二章笔记

来源:互联网 发布:达内培训 大数据 编辑:程序博客网 时间:2024/05/29 16:50

重载操作符可能会造成难以理解的错误,需要注意


条款5:对定制的类型转换函数保持警觉

C++允许编译器在不同类型间执行隐式转换,对自定义类型的转换可以进行控制。

两种函数会允许编译器执行这样的转换:单自变量构造函数和隐式类型转换操作符。

单自变量构造函数指能够以单一自变量成功调用的构造函数,可能拥有单一参数,也可能有多个参数且除第一个参数外都有默认值。

隐式类型转换操作符:关键词operator后加上一个类型名称,无返回值,如:operator double( ) const;

不要提供任何类型转换函数,因为在未知情况下可能被调用,产生不正确的结果,难以调试。

对隐式类型转换操作符,解决办法是以功能对等的另一个函数来取代,比如string类型,不含有从string对象到C类型char*的隐式类型转换,但是提供一个显式的c_str函数执行上述行为。

单自变量构造函数有两种解决方法:简易法使用explicit来声明,禁止隐式类型转换;另一种方法是利用隐式类型转换的一个规则:没有任何一个转换程序可以内含一个以上的用户定制转换行为(亦即单自变量构造函数或隐式类型转换操作符),利用代理类将单自变量改为某一类对象。


条款6:区别自增/自减操作符的前置式和后置式

为区分前置式和后置式,默认在后置式增加一个int参数。

前置式返回一个引用,后置式返回一个const对象。

UPInt& UPInt::operator ++()

{

    *this += 1;

    return *this;

}

const UPInt UPInt::operator ++(int)

{

    UPInt oldValue = *this;

    ++(*this);

    return oldValue;

}

后置式的参数并未使用,只是用来区分前置和后置式,不使用函数的命名参数,编译器会警告,所以此次使用一种策略就是故意略去不准备使用的参数名称。

后置式返回const是为了和内建类型行为保持一致,不允许出现i++++;而++++i是合法的。且即使i++++合法,也并未真正对i自增两次,它只自增一次,因为第二次自增改变的是第一个自增返回的之前的值。

后置式产生了临时对象,效率较低,使用时尽量使用前置式,除非必须使用后置式。

后置式的实现以前置式为基础。


条款7:千万不要重载&& || ,操作符

C/C++真假值的判断采用骤死法,即一旦表达式真假确定,未执行的部分也就不再执行。

C++允许重载&&和||操作符,但你无法保持骤死法语义,所有判断均执行且顺序不能确定。

表达式如果内含逗号,逗号左侧先执行,右侧再执行,最后整个表达式结果以右侧值为代表。重载逗号操作符根本无法模仿以上规则,无法保证左侧比右侧先执行,因为他们被当做函数调用的自变量。


条款8:了解各种不同意义的new和delete

new operator和operator new

我们使用的new就是new operator,它是语言内建的,不能被改变意义,包括两方面动作:一是分配足够内存,用来放置某类型对象,二是调用构造函数为对象初始化。

可以改变的是内存的分配行为,new operator调用某个函数执行必要的分配,可以重载这个函数改变其行为,这个函数名称为operator new。

void* operator new(size_t size);

可以重载operator new,加上另外的参数,但第一个参数类型必须总是size_t。你可以像调用其他函数一样调用operator new返回一块内存,它只负责分配内存,new operator再将其转换为一个对象。

placement new在已分配的原始内存上调用构造函数构建对象:new (buffer) Widget();

在堆上创建对象,使用new operator,分配内存且调用构造函数;只分配内存调用operator new,可以重载operator new决定内存分配方式,new operator会自动调用该函数;在已有内存上构造对象使用placement new。

每个动态分配行为都必须匹配一个释放行为。

operator delete之于delete operator如同operator new之于new operator。内存释放由函数operator delete执行。

void* operator delete(void *memoryToBeDeallocated);

如果只打算处理原始的未设置初值的内存,应完全回避new operator和delete operator,改用operator new和operator delete,这相当于malloc和free。

如果使用placement new在某内存创建对象,应避免对内存使用delete operator,因为delete operator会调用operator delete释放内存,该内存并非operator new得来的,placement new只是返回接收到的内存指针,而不是由它分配的。placement new之后应该调用析构函数抵消构造函数。

数组形式,new operator调用operator new[ ]函数,delete operator调用operator delete[ ]函数。每个元素的构造和析构都被调用。

0 0
原创粉丝点击