C++内存管理

C++内存管理

内存分配层面

学习内存管理主要是为了提高使用内存的效率和速度
C++内存管理
一般而言,C++应用程序使用容器或使用new来申请内存,它们的底层实现都是malloc,很少直接与操作系统API打交道

Primitives

C++内存管理
空间配置器allocator严格来说不算重载,应*设计来搭配容器

四原语实例

C++内存管理
operator new作用域是在全局的
使用空间配置器allocator需要指定分配空间大小,释放时也需要指定,容器适用此方法

new

new有两个动作,一个是分配内存,一个是调用构造函数

new expression

一个new表达式如下

Complex* pc = new Complex(1, 2);

编译器把这行语句转化为

Complex *pc;
try{
    void* mem = operator new( sizeof(Complex) );  //1, allocate
    pc = static_cast<Complex*>(mem);  //2, cast
    pc->Complex::Complex(1, 2);  //3, constructor
}
catch(std::bad_alloc){
    //
}

分配内存在第1行,operator new可重载,底层实现是malloc
第2行把指针转型
第3行调用构造函数,VC6可以通过,其他编译器会失败
要直接调用构造函数,可以使用placement new:

new( p)Complex(1, 2);

对应地,delete表达式:

delete pc;

编译器会转化为

pc->~Complex(); //先析构
operator delete(pc);  //然后释放内存

可以直接调用析构函数
operator delete底层是free

array new

array new例子:

Complex* pca = new Complex[3];
//调用三次constructor
//无法由参数给予初值

delete[] pca;
//调用三次destructor

C++内存管理
构造的pca布局如上图所示,其中cookie包含pca的长度,所有的C++编译器平台设计的malloc和free中的cookie都是如此。

当array new对应的是delete,如果对象没有destructor或destructor是trivial的,则不会发生内存泄漏,否则的话(对象的destructor有意义并且重要)会发生内存泄漏
比如:

int* pi = new int[10];
delete pi; //array new与delete对应,这样写可以,因为int没有destructor

string* psa = new string[3];
delete psa; //错误,只会调用一次destructor,发生内存泄漏

并且根据对象的不同,其内存布局是不一样的
C++内存管理

C++内存管理

placement new

placement new允许将对象建构于已经分配的内存中,形式如下:

#include <new>
char* buf = new char[sizeof(Complex) * 3];
Complex* pc = new(buf)Complex(1, 2);

delete [] buf;

代码首先申请3个Complex大小的内存,用buf指针指向,然后在buf上创建对象

改变内存分配机制

我们已经知道new和malloc是不能重载的,所以可以通过重载operator new来改变内存分配机制
内存分配调用过程如下:
C++内存管理
我们可以重载global functions,来改变内存分配机制,比如在类里重载

Foo::operator new(size_t);

Foo::operator delete(void*);

改变内存分配机制主要是为了去除cookie

上一篇:android桌面悬浮窗实现


下一篇:cv2.putText参数详解