分类: C/C++
2008-09-18 20:40:52
const
int
BUF
=
512
;
class
JustTesting
{
private
:
JustTesting(
const
string
&
s
=
"
Just Testing
"
,
int
n
=
0
)
{
}
~
JustTesting()
{
}
public
:

}
;
int
main()
{
char
*
buffer
=
new
char
[BUF];
JustTesting
*
pc1,
*
pc2,
*
pc3,
*
pc4;
pc1
=
new
(buffer) JustTesting;
pc2
=
new
JustTesting(
"
Heap1
"
,
20
);
pc3
=
new
(buffer
+
sizeof
(JustTesting)) JustTesting(
"
Bad Idea
"
,
6
);
//
此处用一个JustTesging对象大小的偏移量避免pc3与pc1占用同一块内存,因为如果类动态的为其成员分配内存,占用同一内存将会产生问题。
pc4
=
new
JustTesting(
"
Heap2
"
,
10
) 


delete pc2;
delete pc4;
delete [] buffer;
return
0
;
}
以上代码片断中,pc1和pc3为布局new操作符来分配内存,而pc2和pc4为常规new操作符来分配内存 。
对于常规new操作符分配的内存,可以直接使用:delete pc2; 这样的语句操作来释放内存。
而对于布局new操作符分配的内存就不能这样做:delete pc1;
因为pc1和pc3并没有直接收到new操作符返回的地址,而是由布局操作符指向了buffer的地址,new/delete系统知道已分配的512字节块buffer,但对布局new操作符对该内存块做了何种处理一无所知。
另一方面,buffer的地址是用new []初始化的,因此必须使用delete[]而不是delete。
注意:即使buffer是使用new而不是new[]初始化的,delete pc1 也将释放buffer,而不是pc1。
以上的代码确实释放了buffer:delete [] buffer;
但是由此产生了新的问题,它没有为布局new操作符在该内存块中创建的对象调用析构函数,我们只需要在析构函数中放入一段显示语句就可以清楚的看到,程序并没有销毁“JustTesting”和“Bad Idea”,也就是pc1和pc3指向的对象。
那么这里就需要我们显式的为布局new操作符创建的对象调用析构函数。正常情况下将自动调用析构函数,这是需要显示调用析构函数的少数几种情况之一。
显式调用析构函数时,必须指定要销毁的对象。由于有指向对象的指针,因此可以这样写:
把这段代码放到delete [] buffer;之前,这段程序才算完整无错。