9.2.10 存储方案和动态分配(4)
需要指出的第二点是,第二个常规new运算符查找一个新的内存块,其起始地址为006E4B68;但第二个定位new运算符分配与以前相同的内存块:起始地址为00FD9138的内存块。定位new运算符使用传递给它的地址,它不跟踪哪些内存单元已被使用,也不查找未使用的内存块。这将一些内存管理的负担交给了程序员。例如,在第三次调用定位new运算符时,提供了一个从数组buffer开头算起的偏移量,因此将分配新的内存:
第三点差别是,是否使用delete来释放内存。对于常规new运算符,下面的语句释放起始地址为006E4AB0的内存块,因此接下来再次调用new运算符时,该内存块是可用的:
然而,程序清单9.10中的程序没有使用delete来释放使用定位new运算符分配的内存。事实上,在这个例子中不能这样做。buffer指定的内存是静态内存,而delete只能用于这样的指针:指向常规new运算符分配的堆内存。也就是说,数组buffer位于delete的管辖区域之外,下面的语句将引发运行阶段错误:
另一方面,如果buffer是使用常规new运算符创建的,便可以使用常规delete运算符来释放整个内存块。
定位new运算符的另一种用法是,将其与初始化结合使用,从而将信息放在特定的硬件地址处。
您可能想知道定位new运算符的工作原理。基本上,它只是返回传递给它的地址,并将其强制转换为void *,以便能够赋给任何指针类型。但这说的是默认定位new函数,C++(www.cppentry.com)允许程序员重载定位new函数。
将定位new运算符用于类对象时,情况将更复杂,这将在第12章介绍。
6.定位new的其他形式
就像常规new调用一个接收一个参数的new()函数一样,标准定位new调用一个接收两个参数的new()函数:
定位new函数不可替换,但可重载。它至少需要接收两个参数,其中第一个总是std::size_t,指定了请求的字节数。这样的重载函数都被称为定义new,即使额外的参数没有指定位置。