1. void指针
void指针是空类型的指针,它不指向任何类型,仅仅是一个地址。因此void指针不能进行指针运算,也不能直接取其指针所指向的数据的值。
可以将其它类型的指针赋给void指针,但当将void指针赋给其它类型的指针时,必须进行强制类型转换。
2. delete void*
delete void指针指向的对象时,本身不会泄露内存,因为在堆中分配内存的时候,空闲内存是按照链表连接起来的,释放内存则将内存块链到空闲链上面去,关键是分配的时候不只是分配你所需求的内存大小,前面还要分配如下一个结构体内存的大小
struct mem_control_block
{
int is_available;
int size;
};
这称为内存控制块,用于标志此块内存的大小以及是否可用,后面才是实际分配的内存空间,那么不管你的指针是什么
类型的,当调用delete函数的时候,就会将此块内存块的is_available标志标记为可以使用(空闲),等于释放了内存。
但是对于C++的类,确实存在一个问题,因为类型已经丢失,这样不会调用析构函数,如果类里面存在一个指针类型,
指向了另一块内存,可能使得这块内存泄露。而类本身占据的内存不会泄露.
3.delete ,delete[]
例
class A
{
private:
int i;
string s;
public:
~A() { printf("hi"); }
};
void d(A *);
int main(int argc, char* argv[])
{
A *p = new A[10];
d(p);
return 0;
}
void d(A *p)
{
delete p;
}
1.如果对象无析构函数(包括不需要合成析构函数,比如注释掉~A和string s两行代码)
delete会直接调用operator delete并直接调用free释放内存
这个时候的new=new [](仅在数量上有差异),delete=delete[]
2 如果对象存在析构函数(包括合成析构函数),则【这个才是重点】:
new []返回的地址会后移4个字节,并用那4个存放数组的大小!而new不用后移这四个字节
delete[]根据那个4个字节的值,调用指定次数的析构函数 ,同样delete也不需要那四个字节
结果就是在不恰当的使用delete 和delete []调用free的时候会造成4个字节的错位,最终导致debug assertion failed!
4.合成析构函数
合成析构函数按对象创建时的逆序撤销每个非 static 成员,
因此,它按成员在类中声明次序的逆序撤销成员,对于类类型的每个成员,
合成析构函数调用该成员的析构函数来撤销对象撤销内置类型成员或复合类型的成员没什么影响,
尤其是,合成析构函数并不删除指针成员所指向的对象
5.
内存管理