1、操作符与表达式
#include <iostream>
using namespace std;
class A
{
public:
A():a(100),b(200)
{
std::cout << "constructor " << std::endl;
}
~A()
{
std::cout << "destructor " << std::endl;
}
void f()
{
std::cout << a << " " << b << std::endl;
}
private:
int a;
double b;
};
int main()
{
void* p = operator new(sizeof(A)); //<new操作符>,只负责分配内存
p = new (p)A; //<定位new> 在内存块上调用类的构造函数
static_cast<A*>(p)->f();
static_cast<A*>(p)->~A(); //定位new的逆操作,调用析构函数 内存未释放
operator delete(p); //<delete操作符>,只负责释放内存
/*
A* p1 = new A; //<new表达式> 这和上面的效果一样,申请一块内存,然后执行构造函数
p1->f();
delete p1; //<delete表达式> 这和上面的效果一样,调用析构函数 然后释放内存
*/
system("pause");
return 0;
}
2、重载的new/delete
void operator delete(void* p, int t)这个函数也是默认的参数列表,但是只有在void operator delete(void* p)没有提供的时候作为默认;对于多参数重载版本,在new的时候可以直接使用,但是在delete的时候就无法直接调用,直接delete(20) p2使用是非法的。
多参数delete只在相同版本的new在使用的时候,构造函数抛出异常时,并且异常被捕捉的情况下,由系统自动调用。
#include <iostream>
using namespace std;
class A
{
public:
A(){ std::cout << "A::constructor " << std::endl; }
~A(){ std::cout << "A::destructor " << std::endl; }
A(int e)
{
std::cout << "A::constructor throw exception" << std::endl;
throw int(0);
}
void* operator new(size_t size) //默认参数列表new
{
std::cout << "void A::operator new(size_t size)" << std::endl;
return ::operator new(size);
}
void operator delete(void* p)//默认参数列表delete
{
std::cout << "void A::operator delete(void* p)" << std::endl;
return ::operator delete(p);
}
//构造的new/delete
void* operator new(size_t size, int t) //多参数列表new
{
std::cout << "void A::operator new(size_t size, int t) : \t" << t << std::endl;
return ::operator new(size);
}
void operator delete(void* p, int t)//多参数列表delete
{
std::cout << "void A::operator delete(void* p, int t) : \t" << t << std::endl;
return ::operator delete(p);
}
};
class B
{
public:
B(){ std::cout << "B constructor" << std::endl; }
~B(){ std::cout << "B destructor" << std::endl; }
};
class C: public A
{
public:
C(){}
C(int){ throw int(0);}
void* operator new(size_t size) //默认参数列表new
{
std::cout << "void C::operator new(size_t size)" << std::endl;
return ::operator new(size);
}
void operator delete(void* p)//默认参数列表delete
{
std::cout << "void C::operator delete(void* p)" << std::endl;
return ::operator delete(p);
}
};
//全局new/delete
void* operator new(size_t size)
{
std::cout << "void* global::operator new(size_t size)" << std::endl;
return malloc(size);
}
void operator delete(void* p)
{
std::cout << "void global::operator delete(void* p)" << std::endl;
free(p);
}
int main()
{
//普通重载的new/delete
std::cout << "=============================================" << std::endl;
A* p1 = new A; //调用默认参数表的new
delete p1; //调用默认参数表的delete
//多参数重载的new/delete
std::cout << "=============================================" << std::endl;
try
{
A* p2 = new(10) A(0); //调用带多参数的new,使用抛出异常的构造函数构造对象
delete p2; //异常已经跑出,这里不会被调用
}
catch (int)
{
//在这里捕获了异常,那么使用的delete释放资源(就是和new匹配的delete{ void operator delete(void* p, int t) })
}
//全局重载的new/delete
std::cout << "=============================================" << std::endl;
B* pb = new B;
delete pb;
std::cout << "=============================================" << std::endl;
try
{
A* c = new C;
delete c; //正常释放调用的是基类的delete,原因基类的析构不是virtual的,将析构改成virtual就正常了
std::cout << "=============================================" << std::endl;
c = new C(10);
}
catch(...)
{
//抛出异常调用的是派生类的delete释放资源
}
system("pause");
return 0;
}