了解operator new和 operator delete
在库中有两个函数分别是operator new和operator delete。我们知道new作用之一是开辟空间,其底层还是调用了malloc,但与malloc不一样的是当机器执行空间申请操作失败后,malloc返回了一个NULL指针,而new的反应则是抛异常以提供捕获,因此虽然new原则上是调用了malloc,但更进一步说,new是调用了malloc的封装函数operator new,然后再执行类的构造函数,相应的delete是调用了析构函数再调用free的封装函数operator delete,其中operator delete就包含了free。
匹配使用
与new匹配的是delete,new[]匹配的是delete[],以及c语言中malloc和free当二者没有匹配时是否会带来影响?
在这里需要了解delete的原理,当对象的类型为内置类型时,其实没有匹配使用不会带来什么影响(IDE以vs2019为例,注:不同的编译器可能有不同的结果,本次演绎仅供参考)。
int main()
{
int* a = new int;
free(a);
delete a;
delete[] a;
return 0;
}
以上三种方式销毁并没有带来编译器报错,但是这仅仅是对于内置类型!!对于自定义的类,类型不匹配带来的错误时未定义的,而这个问题在被自定义了具有析构函数后尤为明显。
class A
{
public:
A()
:_a(0)
{}
~A()
{
_a = 0;
cout << "~A()" << endl;
}
private:
int _a = 0;
};
int main()
{
// new[] 类型定义对象pst
A* pst = new A[10];
// 使用delete 释放pst指向的空间
delete pst;
return 0;
}
new了十个A类型的对象,最后释放却使用delete,运行结果是这样的
原因就在于new[]在申请空间时,不仅仅申请了指定了10个整形的空间,在这些空间之前,编译器默认申请了四个字节的空间用于保存数字10,然后返回了之后十个空间的指针;这样做是为了之后调用delete[]时,指针向前偏移后获取该int类型里的数据,以便编译器判断进行多少次的析构函数。而最后却调用了delete释放空间,直接引起了指针的误差导致错误。
再次强调--使用的过程务必--匹配使用!!!!
显示调用构造函数——定位new(placement-new)
定位 new 表达式是在 已分配的原始内存空间中调用构造函数初始化一个对象 。使用格式:new (place_address) type 或者 new (place_address) type(initializer-list)place_address 必须是一个指针, initializer-list 是类型的初始化列表