三把大刀
- 第一把 大刀:new
class point_ty{
4. private:
5. int x;
6. int y;
7. public:
8. point_ty(int a, int b)
9. {
10. x = a;
11. y = b;
12. }
13. void show()
14. {
15. cout << "x:" << x << " y:" << y << endl;
16. }
17.
18. };
有如下代码:
point_ty *ptr = new point_ty(1, 2);
其实编译器转化为以下代码:
point_ty *ptr;
try
{
void *mem = operator new(sizeof(point_ty)); //1 分配内存
ptr = static_cast<point_ty *>(mem);//2.类型转换
ptr->point_ty(1,2); //3.调用构造函数(只有编译器可以直接调用构造函数)
}
catch(std::bad_alloc)
{
}
Operator new 可以查看源码如下:
其实也就是使用malloc获得内存
如果使用完毕要释放内存如:delete ptr;
编译器做以下动作:
Ptr->~point_ty();//调用析构函数
Operator delete(ptr);//释放内存
Operator delete的源码如下:
2. 第二把刀 array new
class point_ty{
private:
int x;
int y;
public:
point_ty(int a, int b)
{
x = a;
y = b;
cout << this << " x:" << x << " y:" << y << endl;
}
point_ty():x(0), y(0)
{
cout << this << " x:" << x << " y:" << y << endl;
}
void show()
{
cout <<this<< " x:" << x << " y:" << y << endl;
}
~point_ty()
{
cout << this << " x:" << x << " y:" << y << endl;
}
};
void play()
{
cout << "class point_ty size:" << sizeof(point_ty) << endl;
point_ty *ptr = new point_ty[3];
//地址间隔为8,因为类大小为8
cout << endl;
point_ty *temp = ptr;
for (int i = 0; i < 3;i++)
{
new(temp++)point_ty(i + 1, i + 2);
}
cout << endl;
delete []ptr;
}
可以看出构造函数的执行顺序和析构函数的执行顺序相反。
其中:
point_ty *ptr = new point_ty[3];
//1.会执行三次构造函数
//2.会自带一个cookie,最重要的功能是记录长度。其实也就是为了和free配合。Cookie会占用内存。
如果在释放内存的时候没有加[],即delete ptr;//非delete []ptr;则就会造成内存泄漏三个对象之中只会执行其中一个对象的析构。
在这里要提一点:如果析构函数有意义,在释放的时候如果不加[]就会出错。这里主要是内存解析出错。
先看看普通变量的空间分布图:
然后看看对象空间分布图:
就比如:
point_ty *ptr = new point_ty[5];
现在解释为什么不加[]报错。前提(析构函数有意义),
因为它把析构的时候是从多算了一块就是记录数量的那部分,造成整个布局都乱了。
delete和delete[],在布局上是不同的。Delete []会记录个数
第三把 placement new
其实也就是将对象构建于一个存在的内存中使用方法如下
char *buf = (char *)malloc(sizeof(point_ty));
point_ty *ptr = new(buf)(1,2);
…
Delete buf;
其中编译器将第二句转为:
Point_ty *ptr;
Try
{
Void *mem = operator new(sizeof(point_ty),buf);
ptr = static_cast<point_ty *>(mem);
pc->point_ty(1,2);
}
Catch(std::bad_alloc)
{
}
其中operator new源码如下:
这也就是可以实现自己调用构造函数了。