本文代码中出现的类
class Complex{
public:
int num;
Complex(int _num) : num(_num){}
Complex(){}
~Complex(){}
};
四种常用内存申请方式
//--------四种内存申请方式----------
void* p1 = malloc(512); //申请512bytes
free(p1);
string* p2 = new string; //申请one object
delete p2;
void* p3 = ::operator new(512); //申请512bytes
::operator delete(p3);
int* p4 = allocator<int>().allocate(5); //分配5个int
//int* p4 = allocator<int>().allocate(5, (int*)0); //同上,但是(int*)0并没有必要
allocator<int>().deallocate(p4, 5);
new、delete的解析
//---------------new的解析---------------------
//Complex* cp = new Complex();
//new的实现过程
Complex* cp;
try{
void* men = operator new(sizeof(Complex));
cp = static_cast<Complex*>(men);
//编译器执行为 cp->Complex::Complex(5); 但是我们只能写作如下:
new(cp)Complex(5);
}catch(std::bad_alloc){
}
cout << cp->num << endl;
//-----------delete的解析--------------------
//delete cp;
cp->~Complex();
operator delete(cp); //free(cp);
Array new
//-----------Array new--------------
Complex* cp = new Complex[7];
//----------Array delete------------
delete[] cp;
初始化Arry
class A{
public:
int id;
A() : id(0){ cout << "default ctor.this=" << this << " id=" << id << endl; }
A(int i) : id(i){ cout << "ctor.this=" << this << " id=" << id << endl; }
~A(){ cout << "ctor.this=" << this << " id=" << id << endl; }
};
//-----------初始化一个array-----------------
const int size = 3;
A* buf = new A[size];
A* temp = buf;
cout << "buf = " << buf <<" temp = " << temp << endl;
for(int i = 0; i < size; i++ ){
new(temp++)A(i);
}
cout << "buf = " << buf << " temp = " << temp << endl;
delete[] buf;
基本数据类型的Array new
//-------------------int类型的array new------------------
int *p = new int[5];
delete p; //由于p是int类型,它没有有意义的析构函数,所以这里使用delete与delete[]是一样的
placement new(定位new)
//placement new允许将对象创建于一个已经分配的内纯中,所以要有一个指针代表已经分配好的内存
char* buf = new char[sizeof(Complex)*3]; //buf指针指向的就是提前分配好的内存
Complex* cp = new(buf)Complex(); //将pc创建在buf上,这样pc就不会重新分配内存
//Complex* cp = new(buf)Complex()也可写作如下
//Complex* cp;
//try{
// void* men = operator new(sizeof(Complex), buf); //placement new
// cp = static_cast<Complex*>(men);
// cp->Complex::Complex(); //只有编译器可以这样做,所以这句我们使用时会报错
//}catch(std::bad_alloc){
//
//}
delete[] buf; //没有placement delete因为placement new根本没有分配内存
重载::operator new、::operator delete(不建议这样做)
不建议这样做,全局new与delete被重载的话影响无穷无尽。
#include <iostream>
#include <string>
using namespace std;
class Complex{
public:
int num;
Complex(int _num) : num(_num){}
Complex(){}
~Complex(){}
};
void* myAlloc(size_t size){
return malloc(size);
}
inline void* operator new(size_t size){
cout << "调用了自己重载的new" << endl;
return myAlloc(size);
}
inline void* operator new[](size_t size){
cout << "调用了自己重载的new" << endl;
return myAlloc(size);
}
void myFree(void* ptr){
free(ptr);
}
inline void operator delete(void* ptr){
cout << "调用了自己重载的delete" << endl;
myFree(ptr);
}
inline void operator delete[](void* ptr){
cout << "调用了自己重载的delete" << endl;
myFree(ptr);
}
int main(){
//----------------重载new--------------------
Complex* cp; //这一步cp并没有指向
void* men = operator new(sizeof(Complex));
cp = static_cast<Complex*>(men); //这里cp指向了men开辟的内存
new(cp)Complex(5); //在内存上建立对象
cout << cp->num << endl;
operator delete(cp);
return 0;
}
重载类的operator new、operator delete
#include <iostream>
#include <string>
using namespace std;
class Foo{
public:
Foo(){}
~Foo(){}
void* operator new(size_t size){
Foo *f = (Foo*)malloc(size);
cout << "调用了自己重载的new" << endl;
return f;
}
void* operator new[](size_t size){
Foo *f = (Foo*)malloc(size);
cout << "调用了自己重载的new" << endl;
return f;
}
void operator delete(void* ptr){
cout << "调用了自己重载的delete" << endl;
free(ptr);
}
void operator delete[](void* ptr){
cout << "调用了自己重载的delete" << endl;
free(ptr);
}
};
int main(){
Foo* foo = new Foo[5];
delete[] foo;
return 0;
}
重载placement new
#include <iostream>
#include <string>
using namespace std;
class Foo{
public:
int id;
Foo(int i) : id(i){}
Foo(){}
~Foo(){}
void* operator new(size_t size){
Foo *f = (Foo*)malloc(size);
cout << "operator new(size_t size)" << endl;
return f;
}
void* operator new(size_t size, void* start){
cout << "operator new(size_t size, void* start)" << endl;
return start;
}
void* operator new(size_t size, long ers){
cout << "operator new(size_t size, long ers)" << endl;
return malloc(size + ers);
}
void* operator new(size_t size, long ers, char ch){
cout << "operator new(size_t size, long ers, char ch)" << endl;
return malloc(size + ers);
}
void* operator new[](size_t size){
Foo *f = (Foo*)malloc(size);
cout << "operator new[](size_t size)" << endl;
return f;
}
void operator delete(void* ptr){
cout << "operator delete(void* ptr)" << endl;
free(ptr);
}
void operator delete(void* ptr, long ers){
cout << "operator delete(void* ptr, long ers)" << endl;
free(ptr);
}
void operator delete(void* ptr, long ers, char ch){
cout << "operator delete(void* ptr, long ers)" << endl;
free(ptr);
}
void operator delete[](void* ptr){
cout << "operator delete[](void* ptr)" << endl;
free(ptr);
}
};
int main(){
Foo start;
Foo* f1 = new(&start)Foo;
Foo* f2 = new(100)Foo;
Foo* f3 = new(100)Foo(2);
Foo* f4 = new(100,'c')Foo;
cout << start.id;
return 0;
}
在重载placement new时,第一参数必须是size_t类型,并且最好写上其对应的重载delete.
简单内存池
#include <iostream>
#include <thread>
#include <cstddef>
using namespace std;
class Screen{
public:
Screen(int _i) : i(_i){ }
int get(){ return i; }
void* operator new(size_t);
void operator delete(void*, size_t);
private:
Screen* next;
static Screen* freeStore;
static const int screenChunk;
private:
int i;
};
Screen* Screen::freeStore = 0;
const int Screen::screenChunk = 24;
void* Screen::operator new(size_t size){
Screen*p;
if(!freeStore){
//内存池为空,申请一大堆
size_t chunk = screenChunk * size;
freeStore = p = reinterpret_cast<Screen*>(new char[chunk]);
//将内存池分割
for(; p != &freeStore[screenChunk-1]; ++p)
p->next = p + 1;
p->next = 0;
}
p = freeStore;
freeStore = freeStore->next;
return p;
}
void Screen::operator delete(void* p, size_t){
(static_cast<Screen*>(p))->next = freeStore;
freeStore = static_cast<Screen*>(p);
}
int main(int argc, char** argv) {
cout << "sizeof(Screen) = " << sizeof(Screen) << endl;
size_t const N = 100;
Screen* p[N];
for(int i = 0; i < N; ++i)
p[i] = new Screen(i);
for(int i = 0; i < 10; ++i)
cout << p[i] << endl;
for(int i = 0; i < N; ++i)
delete p[i];
return 0;
}
测试结果发现,分配的内存为连续空间,并且大小为16
如果不使用内存池
#include <iostream>
#include <thread>
#include <cstddef>
using namespace std;
class Screen{
public:
Screen(int _i) : i(_i){ }
int get(){ return i; }
private:
int i;
};
int main(int argc, char** argv) {
cout << "sizeof(Screen) = " << sizeof(Screen) << endl;
size_t const N = 100;
Screen* p[N];
for(int i = 0; i < N; ++i)
p[i] = new Screen(i);
for(int i = 0; i < 10; ++i)
cout << p[i] << endl;
for(int i = 0; i < N; ++i)
delete p[i];
return 0;
}
虽然类的大小变小了,但是数组每个却占用了32个字节