关于newoperator new和deleteoperator delete的看法

    技术2022-05-11  41

    在看过《 Inside the C++ Object Model》的关于new和delete的语意讲解后,对new和delete有了一定程度上的深入了解~~

    当我们使用new给我们的一个对象分配空间的时候。。。new内部的调用实际上是

     

    void* operator new(size_t)

    {

       //alloc memory

       //then call class's constructor

    }

    首先分配了空间。。。但是不会调用我们该类的构造函数

    在这期间,则C++的RTTI机制会进行暗箱操作~~~

    相应的delete也是如此,RTTI也会对其进行干涉

    首先调用该类的析构

    然后再进行释放...

    然而new是一个运算符,并且可以重载,所以在C++中还有一种威力强大的placement new and placement delete

    他的重载则是

    void * operator new(size_t t,void *p)

    {

       return p;

    }

    同理,RTTI也会使new调用相应的构造函数

    但是我们这样做

     

    char *buf=new char[sizeof(typename)];

    typename *obj=(typename*)operator new(sizeof(typename),buf);

    //这句则只会在buf的所指向的堆内存处给我这个类分配一个typename长度的空间,但是不会去调用构造函数

    obj=new(buf) typename;

    //这句则是在buf处分配了空间,并且调用构造函数

    这就是placement new的强大之处,我们可以在指定的内存处进行我们的对象的构造

    但是,如果现在这个对象不需要了,我们还需要在这片内存上构造我们的另一个该类对象,该如何去做呢?

    obj->~typename();//??

    这样可以,但是却显的很生硬

    delete obj;//??

    这句正确,但是同样也释放了obj对象的内存空间,那要怎么做呢?

    所以C++也提供了对应placement new的placement delete

    可以这样进行调用

    delete(buf,obj);

    //这句则不会对obj的内存进行释放,只调用析构函数,所以,我们如果要继续在该片内存上构造对象,可以如下

    typename *_obj=new(buf) typename;

    由此看来,placement new和placement delete的强大之处,可以让程序员更灵活的去操作我们的内存单元,让一片内存连续使用,而省去来回的申请和来回的释放过程,更加的提高了编程的效率。

    不过,有一点,placement new和placement delete不支持多态,倘若我们有如下代码

    struct Base { int j; virtual void f(); };

    struct Derived : Base { void f(); };

    void fooBar()

    {

    Base b;

    b.f();// Base::f() invoked b.

    ~Base();

    new ( &b ) Derived; // placement new

    b.f(); // which f() invoked?

    }

    这是原书上的代码,最后一句,我们调用的f()是哪个类的呢?

    很多用户都希望调用Derived的f(),因为Base中的f()是virtual的

    但事与愿违,经过placement new之后,多态并没有体现出来

    大多的编译器编译后都会去调用Base的f()。

     

    综上,new和delete在内部实现上,是如何去分配空间并调用对应类型的构造函数已经很明了。

    初始其实和C中的malloc和free一样,但是有了RTTI机制,则会在运行时计算类型,从而决定调用哪个类的构造函数。

    RTTI实现时,若类中没有一个虚函数,则将在编译过程中静态的计算类型,更多可以参考《 Inside the C++ Object Model》7.3。

    若至少有一个虚函数存在,则RTTI在运行时动态的计算类型。

     

    好了,这是我看过之后所领悟到的,写到这,怕自己忘记了。

     

     

     

     

     

     


    最新回复(0)