new 一个对象发生了什么?
1、new对象发生的事情
Complex *pc = new Complex(2,4);
当编译器看到上边代码时会做出以下动作:
Complex *pc;
try{
void *mem = operator new(sizeof(Complex));//先分配内存空间
pc = static_cast<Complex*>(mem);//指针转型
pc->Complex::Complex(2,4)//在调用构造函数
}//
delete pc
编译器转为以下做法:
pc->~Complex()//先析构对象
operator delete(pc)//释放内存
看到编译器的操作,我们不仅想自己模仿一下编译器的操作:
我们可以这样做模拟操作系统的做法:
#include<iostream>
#include<string>
#include<memory>
using namespace std;
class A {
public:
int id;
A(int i) :id(i) {
cout << "ctor.this=" << this << "id=" << id << endl;
}
~A() {
cout << "dtor.this=" << this << endl;
}
};
int main() {
A* pA = new A(1);
cout << pA->id << endl;
pA->A::A(3);
cout << pA->id << endl;
pA->A::~A();
}
输出结果:
new 对象怎样发生的?
重载 ::operator new / :: operator delete(这个要小心使用)
#include<iostream>
#include<string>
#include<memory>
using namespace std;
void* myAlloc(size_t size){//模仿全局的
return malloc(size);
}
void myFree(void* ptr){
return free(ptr);
}
inline void* operator new (size_t size){
cout <<"全局的new() \n";
return myAlloc(size);
}
inline void operator delete(void *ptr){
cout <<"全局的delete() \n";
return myFree(ptr);
}
class Foo{
public:
Foo(){
cout << "ctor chenggong \n";
}
~Foo(){
cout << "dtor chenggong \n";
}
};
int main(){
Foo *f = new Foo();
}
重载类中 operator new / operator new[] / operator delete /operatpr delete[]
array new,array delete
Foo *pc = new Foo[3];//唤醒三次默认构造函数,但是无法由参数赋值
delete[] pc //唤醒三次析构函数对于没有指针的成员也可以用 delete pc;具体原因如下图
#include<iostream>
#include<string>
#include<memory>
using namespace std;
class Foo{
public:
int _id;
Foo():_id(0){
cout << "默认构造函数 this:"<< this <<"id = " << _id <<endl;
}
Foo(int i):_id(i){
cout << "构造函数 this:"<< this <<"id = " << _id <<endl;
}
~Foo(){
cout << "dtor.this"<< this << "id=" << _id << endl;
}
};
int main(){
cout <<" sizeof(Foo) ="<< sizeof(Foo) << endl;
Foo *f = new Foo[3];
Foo *tmp = f;
cout << "buf=" << f << "tmp =" <<tmp << endl;
for(int i=0;i<3;i++){
new(tmp++)Foo(i);//调用有参数构造函数
}
cout << "buf=" << f << "tmp=" <<tmp<<endl;
delete[]f;
}
重载类中的operator new 和operator 可以方便我们管理管理内存
具体做法:
class Foo{
public:
static void *operator new(size_t size);
static void operator delete(void* ptr,size_t size)
static void *operator new[](size_t size);
static void operator delete[](void* ptr,size_t size)
}
看例子:
#include<iostream>
#include<string>
#include<memory>
using namespace std;
class Foo{
public:
int _id;
long _data;
string _str;
Foo():_id(0){
cout << "默认构造函数 this:"<< this <<"id = " << _id <<endl;
}
Foo(int i):_id(i){
cout << "构造函数 this:"<< this <<"id = " << _id <<endl;
}
~Foo(){
cout << "dtor.this"<< this << "id=" << _id << endl;
}
static void* operator new(size_t size);
static void operator delete(void* ptr,size_t size);
static void* operator new[](size_t size);
static void operator delete[](void *ptr,size_t size);
};
void* Foo::operator new(size_t size){
Foo *p = (Foo*)malloc(size);
cout<<"重载之后的new";
return p;
}
void Foo::operator delete(void* ptr,size_t size){
cout<<"重载之后的delete";
free(ptr);
}
void* Foo::operator new[](size_t size){
Foo *p = (Foo*)malloc(size);
cout<<"重载之后的new[]";
return p;
}
void Foo::operator delete[](void* ptr,size_t size){
cout<<"重载之后的delete[]";
free(ptr);
}
int main(){
cout <<" sizeof(Foo) ="<< sizeof(Foo) << endl;
Foo *f = new Foo(7);
delete f;
Foo *pArray = new Foo[7];
delete[]pArray;
}
重载new()/delete()
我们可以重载class member operator(),可以写出很多版本,但是每一个版本都必须拥有独特的参数列,并且第一个参数必须是size_t.出现new(args…) 这就是placement new
我们可以重载delete() 并且写出很多版本,但他们绝不会被delete,只用当new所调用的构造函数抛出exception,才会调用这些重载的delete(),只可能这样调用,主要用来归还未能完全创建成功的对象所占用的内存
例子:
#include<iostream>
#include<string>
#include<memory>
#include<exception>
using namespace std;
class Bad{
};
class Foo{
int _i;
public:
Foo(){
cout << "默认构造函数 this:"<< this <<endl;
}
Foo(int i):_i(i){
cout << "构造函数 this:"<< this <<endl;
throw Bad();//抛出异常,测试delete();
}
//1、一般的operator new() 的重载
void* operator new(size_t size)
{
return malloc(size);
}
//2、这个是标准库已经提供的placement new() 的重载形式,模拟一下
void* operator new(size_t size,void *start)
{
return start;
}
//3、新的placement new
void* operator new(size_t size,long extra)
{
return malloc(size+extra);
}
//4、又一个新的placement new
void* operator new(size_t size,long extra,char init)
{
return malloc(size+extra);
}
//对用版本1的
void operator delete(void*,size_t){
cout << "operator delete(void*,size_t)" <<endl;
}
//对用版本2的
void operator delete(void*,void*){
cout << "operator delete(void*,void*)" <<endl;
}
//对用版本3的
void operator delete(void*,long){
cout << "operator delete(void*,long)" <<endl;
}
//对用版本4的
void operator delete(void*,long,char){
cout << "operator delete(void*,long,char)" <<endl;
}
};
int main(){
cout <<" Foo start ="<<endl;
Foo start;
Foo *p1= new Foo;
Foo *p2= new(&start) Foo;
Foo *p3= new(100) Foo;
Foo *p4= new(100,'a')Foo;
Foo *p5= new(100)Foo(1);
Foo *p6= new(100,'a') Foo(1);
Foo *p7= new(&start)Foo(1);
Foo *p8= new Foo(1);
}
出现异常的时候没有调用operator delete(void*,long)