• 动态内存申请的结果——专题2


    实验一:证明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关键字在指定的内存空间上创建对象,此时必须显式的调用构造函数

     

     

  • 相关阅读:
    返回一个一维整数数组中最大子数组的和02
    软工作业04四则运算网页版
    所有子数组的和的最大值
    学习进度表(第五,六周)
    学习进度表(第四周)
    四则运算2的单元测试
    《构建之法》阅读笔记02
    软工作业03
    单元测试练习
    学习进度表(第三周)
  • 原文地址:https://www.cnblogs.com/-glb/p/12302363.html
Copyright © 2020-2023  润新知