实验一:证明new_handler全局函数是否存在
#include <iostream>
#include <new>
#include <cstdlib>
#include <exception>
using namespace std;
class Test
{
int m_value;
public:
Test()
{
cout << "Test()" << endl;
m_value = 0;
}
~Test()
{
cout << "~Test()" << endl;
}
void* operator new (unsigned int size)
{
cout << "operator new: " << size << endl;
// return malloc(size);
return NULL;
}
void operator delete (void* p)
{
cout << "operator delete: " << p << endl;
free(p);
}
void* operator new[] (unsigned int size)
{
cout << "operator new[]: " << size << endl;
// return malloc(size);
return NULL;
}
void operator delete[] (void* p)
{
cout << "operator delete[]: " << p << endl;
free(p);
}
};
//自定义new_handler函数
void my_new_handler()
{
cout << "void my_new_handler()" << endl;
}
void ex_func_1()
{
//在C++中new_handler是一个预定义的函数指针,指向的函数类型为没有返回值,没有参数的函数类型
//set_new_handler将自定义的new_handler函数设置进去,当设置了自定义的函数之后,原来的new_handler函数将作为返回值返回。
//注意,如果在编译器中没有默认的new_handler函数,那么执行完set_new_handler函数后将返回空。
new_handler func = set_new_handler(my_new_handler);
try
{
cout << "func = " << func << endl;
if( func )
{
func();
}
}
//这里想证明默认的处理函数new_handler确实抛出一个bad_alloc的异常。
catch(const bad_alloc&)
{
cout << "catch(const bad_alloc&)" << endl;
}
}
int main()
{
ex_func_1();
return 0;
}
Qt中的编译器打印结果:
func = 0; 说明在该编译器中没有默认的new_handler函数。
使用g++编译器,打印结果:
func = 0; 说明在该编译器中没有默认的new_handler函数
使用Visual studio 2010编译器,打印结果:
func = 00000000,说明在该编译器中没有默认的new_handler函数
使用bcc编译器,打印结果:
func = 某个地址
catch(const bad_alloc&) ,说明在该编译器中确实存在一个new_handler的全局函数。new_hander函数在调用之后,确实抛出了异常。
实验二:当动态申请失败时,统一编译器的行为,提供代码的移植性
#include <iostream>
#include <new>
#include <cstdlib>
#include <exception>
using namespace std;
class Test
{
int m_value;
public:
Test()
{
cout << "Test()" << endl;
m_value = 0;
}
~Test()
{
cout << "~Test()" << endl;
}
void* operator new (unsigned int size)
{
cout << "operator new: " << size << endl;
// return malloc(size);
return NULL;
}
void operator delete (void* p)
{
cout << "operator delete: " << p << endl;
free(p);
}
void* operator new[] (unsigned int size)
{
cout << "operator new[]: " << size << endl;
// return malloc(size);
return NULL;
}
void operator delete[] (void* p)
{
cout << "operator delete[]: " << p << endl;
free(p);
}
};
//自定义new_handler函数
void my_new_handler()
{
cout << "void my_new_handler()" << endl;
}
void ex_func_2()
{
Test* pt = new Test();
cout << "pt = " << pt << endl;
delete pt;
}
int main()
{
ex_func_2();
return 0;
}
利用g++编译器,运行结果如下:
operator new: 4
Test()
段错误
为什么会出现这种现象?
首先是调用了我们自己定义的new,然后分配内存失败,返回一个NULL,然后又在这个NULL上创建了一个对象,去操作0地址,不出现段错误才怪呢。
利用Qt编译器,结果如下:
operator new: 4
Test()
程序崩溃
Visual stdio 2010编译器,结果如下:
operator new: 4
pt = 0
从上面可以看出,3个编译器的行为是不统一的。为了提高程序的移植性,想要统一编译器的行为,又要怎么做呢?
想要统一编译器的行为为:不管哪个编译器,动态内存失败了,直接返回空指针就行了,不要做其他多余的事情了
对new的重载进行异常规格的说明,不管怎样都不会去扔出异常。
void* operator new (unsigned int size) throw()
{
cout << "operator new: " << size << endl;
// return malloc(size);
return NULL;
}
void* operator new[] (unsigned int size) throw()
{
cout << "operator new[]: " << size << endl;
// return malloc(size);
return NULL;
}
运行时结果:
operator new:4
pt = 0
实验三:在单次申请时告诉编译器不管结果是什么,都不要抛出异常。如果申请失败,直接返回空指针
#include <iostream>
#include <new>
#include <cstdlib>
using namespace std;
void ex_func_3()
{
int* p = new(nothrow) int[10];
cout << "pt = " << p << endl;
delete[] p;
int bb[2] = {0};
struct ST
{
int x;
int y;
};
//将ST对象创建到bb这个数组所在的栈空间。如何去做呢?
//在指定的位置创建一个对象,通过new关键字来实现,后面的括号表明地址,即要将对象创建到哪的那个地址。
ST* pt = new(bb) ST();
pt->x = 1;
pt->y = 2;
//目的就是要看看,有没有将ST的对象创建到数组bb所在的内存空间上。
cout << bb[0] << endl;
cout << bb[1] << endl;
//显示的调用析构函数,因为指定了创建对象的空间,此时必须要显式的手动的来调用析构函数了。
pt->~ST();
}
int main()
{
ex_func_3();
return 0;
}
可以使用new关键字在指定的内存空间上创建对象,此时必须显式的调用构造函数