c++应用程序内存分配的四个层面:
侯捷老师总结:
正如图中所示:对于封装好的c++应用程序,内存分配通常包括四层:
- c++标准库里面的std::allocator,
- c++原始代码原语:new, new[], new(), ::operator new(), delete…
- c语言中的malloc 和free
- OS API
正如图中所示,这四层是逐渐靠近底层。封装性逐渐降低。
四层代码的实现:
void *p1 = malloc(512);
free(p1);
complex<int>* p2 = new complex<int>;
delete p2;
void *p3 = ::operator new(512);
::operator delete(p3);
//此处第四种只举一例,经博主亲测可以运行在codeblock上
int *p4=allocator<int>().allocate(5);
allocator<int >().deallocate(p4,5);
new的底层实现过程:
对于compelx *p_complex=new complex(1,2);
实现步骤如下:
- 系统会调用operator new(size_t size)进行内存分配,并将分配的空间的首地址(void*)返回
1.1operator new的底层实现是首先定义一个void*p指针,
1.2while((p=malloc(size))==0)进行判断,如果内存分配失败(也就是内存不够用,实际上我们很难遇到),就会进入一个try,先调用一次set_new_handler()函数,然后对其进行抛出异常。
1.3循环1.2
(这里指的强调的是,typedef void (*new_handler)();new_handler set_new_handler(new_handler p)是由客户自己编写,一般使用来释放无用内存,从而保证p指针的malloc成功)附一张博主测试的代码和结果图
#include<iostream>
using namespace std;
void noMoreMemory()
{
cout<<"no memory"<<endl;
}
int main()
{
set_new_handler(noMoreMemory);
int *p=new int[10000000000000000];
return 0;
}
可见底层代码就是循环调用set_new_handler;
3. 进行指针强转,转换成客户的预期类型(本例中就是complex*)
4. 再执行类内部的构造函数
侯捷老师总结的代码pdf:
//手动重载测试:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
class A
{
public:
A();
virtual ~A();
virtual void sol()
{
cout << "A::sol" << endl;
}
private:
};
A::A()
{
}
A::~A()
{
cout << "~a" << endl;
}
class B:public A
{
public:
int a ;
int b;
B();
~B();
virtual void sol()
{
cout << "B::sol" << endl;
}
void sol2()
{
cout << "B::so2"<< b << endl;
}
void* operator new(size_t size)
{
cout << "my operator new" << endl;
B *p = (B*)malloc(size);
return p;
}
void operator delete(void * phead, size_t size) {
cout << "my operator delete" << endl;
free(phead);
}
void* operator new[](size_t size) {
cout << "my operator new[]" << endl;
B *p = (B*)malloc(size);
return p;
}
void operator delete[](void * phead, size_t size) {
cout << "my operator delete[]" << endl;
free(phead);
}
private:
};
B::B()
{
a = 1;
b = 2;
}
B::~B()
{
cout << "~B" << endl;
}
int main()
{
A *p = new B;
delete p;
A *arr = new A[10];
delete [] arr;
system("pause");
return 0;
}
零碎:
以下三种有默认函数:
- 拷贝构造函数
- 拷贝赋值函数
- 析构函数
- 构造函数
- 移动构造函数(C++2.0)
- 移动赋值函数 (C++2.0)