zoukankan      html  css  js  c++  java
  • 内存管理(一)

    c++ 内存管理(一)

    分配 释放 所属 可否重载
    malloc free() C函数 不可
    new delete C++表达式
    ::operator new() ::operator delete() c++函数
    allocator::allocate() allocator::deallocate() c++标准库 自由搭配任何容器

    new

    A *a = new A();
    

    上面代码我们申请了一个A类的对象使用new。

    new里面的步骤
    1.申请空间
    2.调用A类的构造函数
    3.返回指针

    /**
    new中大概是这样调用的
    */
    A* a=NULL;
    try{
        void* mem = operator new(sizeof(A));//申请内存并返回指针
        a = static_cast<A*>(mem);
        a->A::A();                          //调用构造函数,但是不允许这样做,只有编译器才能主动调用构造函数
    }
    catch(bad_alloc &memExp){
            cerr<<memExp.what()<<endl;
    }
    

    operator new

    那么operator new中又做了什么呢

    /*
    这是一个最简单的重写这个函数的方法,没有处理申请不到内存的情况。
    */
    void* operator new(size_t sz)
    {
        return malloc(sz);
    }
    实际上operator new的伪代码
    void* operator new(std::size_t size)throw(std::bad_alloc)
    {
        using namespace std;
        if(size==0) //处理 0 byte申请
            size=1; //视为 1 byte申请
        while(true)
        {
            尝试分配size bytes
            if(分配成功)
                return 指针(一个指向分配的内存空间的指针)
            //分配失败
            new_hander globalHandler = set_new_handler(0)l
            set_new_hander(globalHandler);
            if(globalHandler)
                (*globalHandler)();
            else
                throw std::bad_alloc();//抛出异常
        }
    }
    

    可以看到operator new中不断尝试申请内存
    new->::operator new->malloc()

    //析构函数
    ~A()
    {
        printf("~A
    ");
    }
    
    //重载operator delete
    void operator delete(void *p)
    {
        printf("free
    ");
        free(p);
    }
    
    //main函数部分
    ...
    a = new A();
    a->~A();
    operator delete(a);
    ...
    
    stdout输出
    ~A
    free
    可以通过指针主动调用析构函数,再用operator delete释放内存
    

    placement new

    有时候我们需要在已经分配的内存上构造新的对象

    class A
    {
    public:
        int a;
        void* operator new(size_t sz)
        {
            return malloc(sz);
        }
        void* operator new(size_t sz,void* p) //什么都不做直接把已经申请的空间返回
            return p;
    };
    int main()
    {
        void *buf = NULL;
        A *a = NULL;
        try
        {
            buf = operator new(sizeof(A));  //申请buf空间
            a = new(buf)A();                //在已申请的空间buf上创建对象
            /*
            这样相当于a = new(buf)A();这一句只执行的构造函数,绕过了a->A::a()这样直接调用构造函数,相当于我们直接调用了构造函数
            */
        }
        catch(bad_alloc &memExp)
        {
            cerr<<memExp.what()<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    第十三章 第六小节 对象移动
    第十二章 动态内存
    Spring mybatis源码篇章-SqlSessionFactoryBean
    Spring aop使用
    Maven pom.xml简单归结
    Maven settings.xml配置解读
    Maven安装
    Tomcat部署WEB应用方式
    【Eclipse】web项目部署新手篇
    Oracle客户端工具安装
  • 原文地址:https://www.cnblogs.com/xcantaloupe/p/10582236.html
Copyright © 2011-2022 走看看