STL-从list节点创建和释放展开(内存管理)
0 内存管理概述
list的内存管理,实际上就是对list节点的管理。容器每增加或删除一个节点,都涉及内存的分配和释放。
0.1 为何会有内存管理?
通常来说,某个程序在运行初期总会向系统申请一定的内存,只有当已申请的内存不够时,才会在此向系统申请。这一设计一方面是为了降低频繁的系统调用,另一方面也是为了提高内存分配效率。
也就是说,对于任何一个程序,其内部都有一个,所谓“局部内存管理器”。本节所讲的内存管理指的便是这个“局部内存管理器”,用于管理STL相关容器的内存分配。
0.2 STL中区分内存分配和构造/析构
在这里,我们首先要区分两点:内存空间的配置/释放 和 对象内容的构造/析构。
在对象的构造和析构中,主要涉及变量的初始化和部分申请内存的释放。
程序只要运行,就离内存的分配和释放。
为了体现这两者的差别,我们看placement new的使用:
在以往的使用习惯中,我们常见的C++用法是:
#include <iostream>using namespace std;
class A{
public:int a;A(int value):a(value){};
};int main(){A * a_ptr = new A(10);cout << a_ptr->a << endl;
}
而placement new的用法,允许你在一块儿指定的地址上构建:
#include <iostream>
#include <new>
#include <malloc.h>
using namespace std;
class A{
public:int a;A(int value):a(value){};
};int main(){void * n_ptr= malloc(sizeof(A));cout << n_ptr << endl;new (n_ptr) A(10);cout << n_ptr << endl;cout << ((A *)n_ptr)->a << endl;
}
1 节点的创建、释放、构造和析构
1.1 基本形式
在这里插入代码片
1.2 全局的构造和析构
在1.1中,我们使用到了全局的构造和析构函数,其具体内容如下:
// construct.h中
template <class T1, class T2>
inline void construct(T1 *p, const T2 & value){new (p) T1(value);// 调用T1::T1(value);
}//destory的多个版本
template <class T>
inline void destroy(T * pointer){pointer->~T();//调用T::~T();
}
这里的构造和析构函数有多个版本(用于接收不同的入口参数)(这里仅列举两个。)
仔细观察上述函数可知,这个函数是一个“套壳”函数。归根节点,该函数调用的是对象T1/T的构造函数和析构函数。对于list来说,调用的就是list::list()和list::~list()(暂时不考虑入口参数)。
对于其他STL容器来说也一样。某个容器具体的构造和析构定义在自定的类定义中。
这里仅列举几个有代表性的list类的构造和析构。