new和delete的基本用法:
#include <iostream>
#include <stdlib.h>
#define N 10
using namespace std;
class test
{
private:
int a;
public:
test(int d=0)
{
a=d;
cout<<"构造函数"<<endl;
}
~test()
{
cout<<"析构函数"<<endl;
}
};
int main()
{
//一个变量空间
int *p=(int*)malloc(sizeof(int ));
if(p==NULL)//malloc开辟空间需要判断一下是否成功,new不需要
{
exit(1);
}
*p=2;
free(p);
int *q=new int(2);//如果new一个变量可以在初始化的时候赋值,
delete q;
//一个数组
int *p2=(int *)malloc(sizeof(int )*N);
if(p2==NULL)
{
exit(1);
}
free(p2);
int *q2=new int[N];//不要和上面的圆括号混淆了
delete []q2;//前面加一个[]来区分是一个变量还是数组;(方括号里面的数字没用.编译器自动忽略.无聊的话可以随便填....)
//一个对象
test* p3=(test*)malloc(sizeof(test));
if(p3==NULL)
exit(1);
*p3=test(3);//见下面
//如果对象里面有指针变量,这里必须释放对象内部指针变量指向的空间,相当与析构函数的功能;
free(p3);
cout<<"上面是malloc,下面是new"<<endl;
test* q3=new test;
delete q3;
/*跑一遍你会发现
malloc没有调用构造析构函数,只会申请空间,
new,申请空间,并会调用相应的构造函数.
malloc free没有调用构造析函数,就没有完成相应的对象初始化和析构变量(对对象内部指针变量的释放);
所以就要在内存申请完毕后再对对象进行初始化,在free前要对对象内部的指针变量进行释放,否则就会造成内存泄露;
*/
test* q4=new test[N];//new的时候我们没办法给出初始化的参数(构造函数的参数),所以我要使用new数组的时候对象必须要有默认(无参)的构造函数;
delete []q4;//再次提醒数组一定要加[];
cout << "Hello world!" << endl;
return 0;
}
new的深入理解
对于new的重载,operator new 和 定位new;
#include <iostream>
#include <string.h>
#include <stdlib.h>
using namespace std;
class test
{
private:
char *a;
public:
test(const char *const d="")
{
if(d==NULL)
{
a=new char[1];
a[0]=0;
}
else
{
a=new char[strlen(d)+1];
strcpy(a,d);
}
cout <<"构造函数"<<endl;
}
~test()
{
delete []a;
a=NULL;
cout <<"析构函数"<<endl;
}
// void * operator new(size_t len);
// void operator delete(void * p);
};
/*
前面我们说过 new 在调用的时候会首先开辟空间(而且底层还是malloc实现),然后再调用构造函数.
这个就是我们经常使用的new,叫做new operator(new 操作符);delete也是一样的,顺序与new相反(先调用析构函数,在对地址进行释放);
那么,new是怎么开辟空间的呢?
new在开辟空间时 调用的是operator new(操作符new);(operator new 在汇编是用malloc实现);
我们知道了两个new的区别,但这个operator new 有什么用呢?
new和delete都是用算符,可以被重载,我们说的operator new就是这个用法,我们可以重载operator new 来自己定义new开辟开辟空间的方法;
*/
void * operator new(size_t len)//size_t 就是 int ,这里要说 第一个参数 必须是一个无符号整形;返回类型是void* 需要在返回的地方进行强转
{
cout<<"operator new"<<endl;
void *p=malloc(len);
return p;
}
void operator delete(void * p)
{
cout <<"operator delete"<<endl;
free (p);
}
//对与数组的operator new;
void * operator new[](size_t len)
{
cout <<"operator new []"<<endl;
void *p=malloc(len);
return p;
}
void operator delete[](void *p)
{
cout <<"operator delete []"<<endl;
free(p);
}
//定位new的重载
template <typename type>
void * operator new (size_t len,type *d,int n=0)//讲type类型的指针传入进来,返回需要构造的地址,他会自己给你构造.
{
return d+n;
}
int main()
{
//test p("wahaha\n");
test *p1=new test("wahaha1/n");
delete p1;
//我们会发现使用 new操作符 时会向我们说的先调用 操作符new 来开辟空间,然后再调用析构函数;delete也是一样.
//就像下面的过程一样
test * p2=(test *)operator new(sizeof(test));//先用 operator new 开辟空间
new(p2)test("wahaha2/n");//这里是new的第三种用法,叫做定位new
p2->~test();//主动调用析构函数,但是构造函数不能主动调用,所以上面构造对象 使用了定位new的用法
operator delete(p2);//释放空间
test *p3=new test[3];//对数组的使用
delete []p3;
//定位new,是可以将你传入的指针的地方进行一次构造函数,
int aa[10];
new(aa,3)int(4);
new(aa,4)int(1234);
new(aa)int(34);
for(int i=0;i<10;i++)
cout <<aa[i]<<endl;
cout << "Hello world!" << endl;
return 0;
}