• New


    今天,我们只讲new。

    1. new operator

    new操作符(new operator)比较容易理解,相信对C++比较熟悉的人,对下面的代码都不会觉得陌生。这是使用new 最常见的形式。
    class A{
    ....
    };
    std::shared_ptr<A> a(new A);
    new operator实际上就是: 分配内存+调用构造函数初始化。
    2. operator new
    new operator和operator new虽然差不多,但是你不可以把它们等同起来。与new operator相比,operator new 少了构造初始化的部分,它与malloc比较像。
    operator new的声明一般为:
    void * operator new(size_t size);
    需要注意的是,operator new返回一个未经过处理的指针(类型是void*)。new operator调用operator new来分配内存,operator new也能够被重载。
    默认的operator new 重载版本有:
    void * operator new(std::size_t count) throw(std::bad_alloc); //normal new
    void * operator new(std::size_t count, void *ptr)throw(); //placement new
    void * operator new(std::size_t count, const std::nothrow_t&)throw();//nothrow new, 为了兼容以前的版本
    我们来看一下operator new的源码:
    void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc)
    __attribute__((__externally_visible__));
    void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc)
    __attribute__((__externally_visible__));
    •  _GLIBCXX_THROW: 指定该函数抛出的异常,C++11后该宏为空
    • __attribute__: GCC使用__attribute__关键字来描述函数,变量和数据类型的属性,用于编译器对源代码的优化。
    • __externally_visible__: GCC的优化参数,详情:https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html
     
    3. placement new
    所谓定位放置(placement new)就是在用户指定的内存位置上构建新的对象,这个构建过程不需要额外分配内存,只需要调用对象的构造函数即可。
    class A{
    ....
    };
    int main(){
    char mem[100];
    A* p=new (mem) A;
    p->~A();
    return 0;
    }
    operator new和placement new的关系:
    class A{
    ....
    };
    
    A* p=new A(10);//有参构造
    //等同于下面的调用
    void* mem=malloc(sizeof(A));
    A* p=new (mem) A(10);
    看似神奇的placement new实际上是operator new的一个全局重载版本,它实际上做了这么一件事(我们来看一下源码):
    // Default placement versions of operator new.
    inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
    { return __p; }
    inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT
    { return __p; }

     我们可以看到实际上它不加任何处理直接返回了指针。那么函数的两个参数从哪来?

    其实,当我们写了下面的代码时:
    A* p=new (mem) A;
    实际上,转变为了:
    operator new (sizeof(A), men);
    到这里,就知道上面源码的operator new两个参数是什么了吧。
    4. 重写operator new
    这部分省略(网上的资料有不少):
    https://www.cnblogs.com/cly-blog/p/5984660.html
    5. 总结
    看到这里,你是否对new operator、operator new、placement new有了一个全面的了解,下面我们来总结一下:
    • new operator:分配内存+调用构造函数
    • operator new:分配内存
    • placement new:在已分配的内存里调用构造函数
    • 假设你想定制自己的在堆对象被建立时的内存分配过程,你应该写你自己的operator new函数。然后使用new操作符,new操作符会调用你定制的operator new。

     
    生命中所有的灿烂,终要寂寞偿还。——《百年孤独》
  • 相关阅读:
    使用迭代器模式批量获得数据(C#实现)
    如何从技术上预防抢票软件刷屏
    如何用Tesseract做日文OCR(c#实现)
    我的.net开发百宝箱
    程序员必备基础:Git 命令全方位学习
    Java 异常处理的十个建议
    50道Java集合经典面试题(收藏版)
    记一次接口性能优化实践总结:优化接口性能的八个建议
    100道MySQL数据库经典面试题解析(收藏版)
    800+Java后端经典面试题,希望你找到自己理想的Offer呀~
  • 原文地址:https://www.cnblogs.com/ZWJCNBLOG/p/11509007.html
Copyright © 2020-2023  润新知