能力强的人善于解决问题,有智慧的人善于绕过问题。 区别很微妙,小心谨慎做后者。
全部博文(399)
分类: LINUX
2010-08-09 09:39:00
new操作符(new operator)就象sizeof一样是语言内置的,你不能改变它的含义(注意,这里是说new操作符,而不是new函数),它的功能总是一样的。它要完成的功能分成两部分。第一部分是分配足够的内存以便容纳所需类型的对象。第二部分是它调用构造函数初始化内存中的对象。new操作符总是做这两件事情,你不能以任何方式改变它的行为。
你所能改变的是如何为对象分配内存。new操作符调用一个函数来完成必需的内存分配,你能够重写或重载这个函数来改变它的行为。new操作符为分配内存所调用函数的名字是operator new。
函数operator new 通常这样声明:
void * operator new(size_t size);
返回值类型是void*,因为这个函数返回一个未经处理(raw)的指针,未初始化的内存。(假如你喜欢,你能写一种operator new函数,在返回一个指针之前能够初始化内存以存储一些数值,但是一般不这么做。)参数size_t确定分配多少内存。你能增加额外的参数重载函数 operator new,但是第一个参数类型必须是size_t。
你一般不会直接调用operator new,但是一旦这么做,你可以象调用其它函数一样调用它:
void *rawMemory = operator new(sizeof(string));
操作符operator new将返回一个指针,指向一块足够容纳一个string类型对象的内存。
就象malloc一样,operator new的职责只是分配内存。它对构造函数一无所知。operator new所了解的是内存分配。把operator new 返回的未经处理的指针传递给一个对象是new操作符的工作。
在STL的vector里面的分配器就是直接使用了 operator new 函数来分配内存
int *ptr=new int [5];
这个语句实现了,在堆中查找一块足够存储一个拥有5个整形数的数组的内存,且数组的首地址赋予了指针ptr。
Placement new
有时你确实想直接调用构造函数。在一个已存在的对象上调用构造函数是没有意义的,因为构造函数用来初始化对象,而一个对象仅仅能在给它初值时被初始化一次。但是有时你有一些已经被分配但是尚未处理的的(raw)内存,你需要在这些内存中构造一个对象。你可以使用一个非凡的operator new ,它被称为placement new。
template
inline void passive_vector
{
//new(static_cast
new(p) T();
}
template
inline void passive_vector
{
//new(static_cast
new(p) T(val);
}
注意,必须include
上面的函数,在已经分配好的内存p上执行一个构造函数T()
这是new操作符的一个用法,需要使用一个额外的变量(p),当new操作符隐含调用operator new函数时,把这个变量传递给它。被调用的operator new函数除了待有强制的参数size_t外,还必须接受void*指针参数,指向构造对象占用的内存空间。这个operator new就是placement new,它看上去象这样:
void * operator new(size_t, void *location)
{
return location;
}
这可能比你期望的要简单,但是这就是placement new需要做的事情。在使用placement new的情况下,调用者已经获得了指向内存的指针,因为调用者知道对象应该放在哪里。placement new必须做的就是返回转递给它的指针。
placement new是标准C++库的一部分, 为了使用placement new,你必须使用语句#include
总结:
1)你想在堆上建立一个对象,应该用new操作符。它既分配内存又为对象调用构造函数。
2)你仅仅想分配内存,就应该调用operator new函数;它不会调用构造函数。
3)你想定制自己的在堆对象被建立时的内存分配过程,你应该写你自己的operator new函数,然后使用new操作符,new操作符会调用你定制的operator new。
4)你想在一块已经获得指针的内存里建立一个对象,应该用placement new。
类似地,也有delete操作符和delete函数