首页 > 编程语言 > C/C++ > More Effective C++读书笔记(二)
2019
11-29

More Effective C++读书笔记(二)

1、不要试图重载||,&&操作符,因为它们使用短路求值法(一旦确定了布尔表达式的真假值,即使还有部分表达式没有被测试,布尔表达式也停止运算),而重载之后采用的是函数调用法。首先当函数被调用时,需要运算其所有参数,所以调用函数functions operator&& 和 operator||时,两个参数都需要计算,换言之,没有采用短路计算法。第二是C++语言规范没有定义函数参数的计算顺序,所以没有办法知道表达式1与表达式2哪一个先计算。完全可能与具有从左参数到右参数计算顺序的短路计算法相反。同样,也不要试图重载逗号(,)操作符,因为一个包含逗号的表达式首先计算逗号左边的表达式,然后计算逗号右边的表达式,整个表达式的结果是逗号右边表达式的值,这也可能和函数调用法对参数的计算顺序不同。因为重载操作符很重要的一点就是要重载之后行为特性与其被料想(缺省的行为特征)的一样。否则,重载是完全轻率的行为。C++规定不能重载的操作符有., .*, ::, ?:,new, delete, sizeof, typeid,static_cast, dynamic_cast, const_cast, reinterpret_cast

2、理解各种不同含义的new和delete(new操作符和operator new操作),先分析一段代码:
string *ps = new string("Memory Management");
使用的new是new操作符。这个操作符就象sizeof一样是语言内置的,你不能改变它的含义,它的功能总是一样的。
它要完成的功能分成两部分:第一部分是分配足够的内存以便容纳所需类型的对象。第二部分是它调用构造函数初始化内存中的对象。new操作符总是做这两件事情,你不能以任何方式改变它的行为(不能重载)。
完成new操作符功能的第一部分分配内存所调用函数的名字是operator new(可以重载)。
函数operator new 通常这样声明:
void * operator new(size_t size);
返回值类型是void*,因为这个函数返回一个未经处理(raw)的指针,未初始化的内存。参数size_t确定分配多少内存。你能增加额外的参数重载函数operator new,但是第一个参数类型必须是size_t。operator new的职责只是分配内存(返回一个void *指针,有点类似C语言的malloc)。它对构造函数一无所知。
当你的编译器遇见这样的语句:
string *ps = new string("Memory Management");
它生成的代码或多或少与下面的代码(伪码)相似:
void *memory = operator new(sizeof(string)); // 得到未经处理的内存
call string::string("Memory Management") on *memory;// 为String对象初始化
string *ps = static_cast<string*>(memory); //内存中的对象是ps指针指向新的对象

同样,我们分析定位new操作符,例如:
new (buffer) Widget(widgetSize)
当该定位new操作符隐含调用operator new函数时,把这个变量(内存地址buffer)传递给它。被调用的operator new函数除了待有强制的参数size_t外,还必须接受void*指针参数,指向构造对象占用的内存空间。这个operator new就是placement new,它看上去象这样:
void * operator new(size_t, void *location)
{
return location;
}
总结:
如果想在堆上建立一个对象,应该用new操作符。它既分配内存又为对象调用构造函数。如果你仅仅想分配内存,就应该调用operator new函数;它不会调用构造函数。如果你想定制自己的在堆对象被建立时的内存分配过程,你应该写你自己的operator new函数,然后使用new操作符,new操作符会调用你定制的operator new。如果你想在一块已经获得指针的内存里建立一个对象,应该用placement new。

对于delete和operator delete也有类似的结论:
delete 先调用析构函数,然后调用operator delete释放内存,而operator delete仅仅是释放内存。如果你用placement new在内存中建立对象,你应该避免在该内存中用delete操作符。因为delete操作符调用operator delete来释放内存,但是包含对象的内存最初不是被operator new分配的,placement new只是返回转递给它的指针。谁知道这个指针来自何方?而你应该显式调用对象的析构函数来解除构造函数的影响。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/digu/archive/2007/11/13/1882023.aspx

最后编辑:
作者:搬运工
这个作者貌似有点懒,什么都没有留下。