admin管理员组

文章数量:1130349

Memory allocation详解

在C++中,我们可以很方便的动态分配内存,那么动态分配后的初始化顺序和释放内存时候的析构顺序究竟是怎样的呢,我们来回顾一下
首先我们想看一个案例:

首先假设我们有一个User类

class User{
public:
	User(std::string str,int i):name(str),val(i){data=new char[100];}
	~User(){delete[] data;}
private:
	std::string name;
	int val;
	char*data;
};

我们写了以下的测试demo

int main() {
    User*user;
    user=new User("你好",12);		//分配内存且调用构造
    cout<<&user<<endl;
    delete user;				 //释放内存且调用析构
    cout<<&user<<endl;
    return 0;
}

我们可以看到下面的输出
new path: 0x65fee0
delete path: 0x65fee0
有的人可能就好奇了,不是说归还内存么,为什么我获得user的地址还是那个地址呢,其实其实内存中存储的数据已经释放了,现在根本不知道里面是什么东西,这种情况下你千万不要去使用它了,因为已经不知道是哪个程序使用了这块内存.这种称为野指针。
我们应该规范的去写程序,上面呢这里有一点就很不规范,首先我们要为分配内存前给它初始化为nullptr ,而归还内存后也要手动将他赋值为nullptr ,为什么这么做呢,我想你做的多了就会了解了,这里还是提一下,因为你不手动置为nullptr的话他就算归还了内存还是指向原来的地址,而且if判断是可以过的,这就会有大问题,我们还是将他手动置空
nullptr:空指针,也有人问为什么不能用
NULL
呢,其实也可以但是在
cpp11后就很不规范了,首先我们要明白NULL是什么,NULL其实也可以说是 #define NULL 0 ,那这样的话,假设我有一个模板函数和一个需要指针参数的函数,我传递来了一个NULL,那么你猜它会调用哪个,如果我告诉你它会调用模板函数,你是不是很意外他调用的将会是func(int)这样的方式,那如果我传nullptr呢,那么它调用的将是那个需要指针参数的函数。
我们现在写一下规范避免错误的写法

int main() {
    User*user= nullptr;
    user=new User("你好",12);
    delete user;
    user=nullptr;		//可以尝试将这行注释在取消注释测试
    if(user!=nullptr)
    	cout<<"true"<<endl;
    return 0;
}

测试完这个程序的注释nullptr就会清楚为什么我会说要手动置空了
new的话它在暗中进行了什么操作呢,根据侯捷老师讲课提到的概念是这样的

User user=new User("你好",12);
/*---------------------------可以分解为以下三个步骤---------------------------*/
void*temp=operator new(sizeof(User));	   //分配内存
user=static_cast<User*>(temp);			  //类型转换
user->User::User("你好",12);				//调用构造
/*--------------------------------------------------------------------------*/
delete user;
/*---------------------------可以分解为以下两个步骤---------------------------*/
User::~User(user);						//调用析构
operator delete(user);					//归还内存

那么可能上面的operator newoperator delete 会看的很头疼呀,没见过这些等等等等,那么学过C语言的同学可以把它看作mallocfree 这样是不是好了很多呢。

那么我们为什么在分配内存时是先分配内存后调用构造,删除时先调用析构后归还内存呢,这里我们可以这么理解,我们首先要有一个家才能装修这个家,那么怎么理解归还内存呢,其实也很好理解,我们要搬家时肯定要把自己的东西带走了,不然你在那里摆一大堆的东西,你愿意你问问房东愿意么,同理我们归还内存的话就是假设我里面有一个指针指向了数组,我肯定是要把这个数组释放掉,不然留着的话我都已经退房了,不仅没办法在回来继续住,而且还会对其他客人造成影响,其实就是这么简单!

Memory allocation详解

在C++中,我们可以很方便的动态分配内存,那么动态分配后的初始化顺序和释放内存时候的析构顺序究竟是怎样的呢,我们来回顾一下
首先我们想看一个案例:

首先假设我们有一个User类

class User{
public:
	User(std::string str,int i):name(str),val(i){data=new char[100];}
	~User(){delete[] data;}
private:
	std::string name;
	int val;
	char*data;
};

我们写了以下的测试demo

int main() {
    User*user;
    user=new User("你好",12);		//分配内存且调用构造
    cout<<&user<<endl;
    delete user;				 //释放内存且调用析构
    cout<<&user<<endl;
    return 0;
}

我们可以看到下面的输出
new path: 0x65fee0
delete path: 0x65fee0
有的人可能就好奇了,不是说归还内存么,为什么我获得user的地址还是那个地址呢,其实其实内存中存储的数据已经释放了,现在根本不知道里面是什么东西,这种情况下你千万不要去使用它了,因为已经不知道是哪个程序使用了这块内存.这种称为野指针。
我们应该规范的去写程序,上面呢这里有一点就很不规范,首先我们要为分配内存前给它初始化为nullptr ,而归还内存后也要手动将他赋值为nullptr ,为什么这么做呢,我想你做的多了就会了解了,这里还是提一下,因为你不手动置为nullptr的话他就算归还了内存还是指向原来的地址,而且if判断是可以过的,这就会有大问题,我们还是将他手动置空
nullptr:空指针,也有人问为什么不能用
NULL
呢,其实也可以但是在
cpp11后就很不规范了,首先我们要明白NULL是什么,NULL其实也可以说是 #define NULL 0 ,那这样的话,假设我有一个模板函数和一个需要指针参数的函数,我传递来了一个NULL,那么你猜它会调用哪个,如果我告诉你它会调用模板函数,你是不是很意外他调用的将会是func(int)这样的方式,那如果我传nullptr呢,那么它调用的将是那个需要指针参数的函数。
我们现在写一下规范避免错误的写法

int main() {
    User*user= nullptr;
    user=new User("你好",12);
    delete user;
    user=nullptr;		//可以尝试将这行注释在取消注释测试
    if(user!=nullptr)
    	cout<<"true"<<endl;
    return 0;
}

测试完这个程序的注释nullptr就会清楚为什么我会说要手动置空了
new的话它在暗中进行了什么操作呢,根据侯捷老师讲课提到的概念是这样的

User user=new User("你好",12);
/*---------------------------可以分解为以下三个步骤---------------------------*/
void*temp=operator new(sizeof(User));	   //分配内存
user=static_cast<User*>(temp);			  //类型转换
user->User::User("你好",12);				//调用构造
/*--------------------------------------------------------------------------*/
delete user;
/*---------------------------可以分解为以下两个步骤---------------------------*/
User::~User(user);						//调用析构
operator delete(user);					//归还内存

那么可能上面的operator newoperator delete 会看的很头疼呀,没见过这些等等等等,那么学过C语言的同学可以把它看作mallocfree 这样是不是好了很多呢。

那么我们为什么在分配内存时是先分配内存后调用构造,删除时先调用析构后归还内存呢,这里我们可以这么理解,我们首先要有一个家才能装修这个家,那么怎么理解归还内存呢,其实也很好理解,我们要搬家时肯定要把自己的东西带走了,不然你在那里摆一大堆的东西,你愿意你问问房东愿意么,同理我们归还内存的话就是假设我里面有一个指针指向了数组,我肯定是要把这个数组释放掉,不然留着的话我都已经退房了,不仅没办法在回来继续住,而且还会对其他客人造成影响,其实就是这么简单!

本文标签: 详解memoryallocation