Placement new(174)

Placement new

先看一段代码:++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template<class T1,class T2>
inline void _construct(T1* p,const T2& value)
{
new(p) T1(value);
}
int _tmain(int argc, _TCHAR* argv[])
{
int p = 0;
int t = 0;
_construct(&p, 3);
cout << &p << endl << &t << endl;
system("pause");
return 0;
}
//神奇的new的用法
//居然对p进行返回了
//这个使用的就是Placement new
  • 先回顾下知识

    new和delete操作符我们应该都用过,它们是对堆中的内存进行申请和释放,而这两个都是不能被重载的。
    要实现不同的内存分配行为,需要重载operator new和operator delete,而不是new和delete。
    operator new就像operator+一样,是可以重载的。
    但是不能在全局对原型为void operator new(size_t size)这个原型进行重载,一般只能在类中进行重载。
    如果类中没有重载operator new,那么调用的就是全局的::operator new来完成堆的分配。

    同理,operator new[]、operator delete、operator delete[]也是可以重载的。

  • 讲解

  • placement new,只是operator new的一个重载的版本
  • placement new允许你在一个已经分配好的内存中(栈或者堆中)构造一个新的对象。
    原型中void*p实际上就是指向一个已经分配好的内存缓冲区的的首地址。
  • placement new非常适合那些对时间要求比较高,长时间运行不希望被打断的应用程序(因为没有new去查询空间内存了,直接提前预定义好了)
  1. 缓冲区提前分配,可以使用堆的空间,也可以使用栈的空间。所以分配方式有如下两种:

class MyClass {…};
char buf=new char[Nsizeof(MyClass)+sizeof(int)];
char buf[N*sizeof(MyClass)+sizeof(int)];

  1. 对象的构造
    MyClass * pClass=new(buf) MyClass; //new(buf) MyClass(int) 这里还可以这样用,给个传递值

  2. 对象的销毁
    一旦这个对象使用完毕,你必须显式的调用类的析构函数进行销毁对象。但此时内存空间不会被释放,以便其他的对象的构造。
    pClass->~MyClass();

  3. 内存的释放
    如果缓冲区在堆中,那么调用delete[] buf 进行内存的释放。如果在栈中,那么在其作用域内有效,跳出作用域,内存自动释放。

先看一段代码:++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
template<class T1,class T2>
inline void _construct(T1* p,const T2& value)
{
new(p) T1(value);
}
template<class T1,class T2>
inline T1* _constructs(T1* p,const T2& value)
{
return new(p) T1[3];
}
class MemT {
public:
int m_a;
MemT(size_t a) { m_a = a; cout << a << endl;}
~MemT() {}
void * (operator new) (size_t t, void *location)
{
return location;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
int p = 0;
int d[3] = {0};
MemT* da = new (&p) MemT(2);//先走操作符,再走构造 别忘了析构
_construct(&p, 3);
_constructs(&d, 2);
system("pause");
return 0;
}
//类的那块,本来就没啥代码,最多给个分配内存的判断和内存的再开辟吧。
//数组那块_constructs,有个遗憾,无法像第一个那样给参数进去。
//能用的场景:1、基本数据配子(给基类数据都开辟大小,通过这个来构造析构)也就STL敢用!
//2、节约内存,对已经使用了的内存,再次使用。感觉并无多大用

原作:
http://www.cnblogs.com/younes/archive/2010/04/26/1721528.html

// //