深入剖析C++中的三种new

来源:互联网 发布:直播平台用户数据分析 编辑:程序博客网 时间:2024/06/03 19:47
  1. new运算符
  2. Operator new()函数
  3. placement new

我们平时调用的new运算符底层调用的就是Operator new()函数(功能和malloc一模一样),如果是内置类型或者没有重载new运算符的自定义类型,那么将调用全局Operator new(),如果重载了将调用局部的Operator new(),如果这个类型有构造函数,new还是调用构造函数(注意调用构造函数之前还会吧operator new()的返回值检查一下,如果等于0那么就不调用构造函数)

验证1:new运算符底层调用的就是Operator new()函数

class A{public:    A(){ cout << "构造" << endl; }    int a;};int test2(){    A *b = new A;    return 0;}

这里写图片描述

验证2:内置类型或者没有重载new运算符的自定义类型,那么将调用全局Operator new(),重载了将调用局部的Operator new()

没有重载的汇编代码刚才已经看了,现在看一个重载之后的。
这里写图片描述
区别很明显吧!!

验证3:如果这个类型有构造函数,new还是调用构造函数
还是第一段代码
这里写图片描述

第二段代码(没有构造)
这里写图片描述
再看一个内置类型,和上面一模一样
这里写图片描述

验证4:构造函数之前还会吧operator new()的返回值检查一下,如果等于0那么就不调用构造函数
我们来重载一下new操作符

class A{public:    A(){ cout << "构造" << endl; }    int a;    void * operator new(size_t size)    {        cout << "dong" << endl;        return NULL;    }};int test2(){    A *b = new A;    return 0;}

看一下汇编
这里写图片描述
最终执行的结果
这里写图片描述

如果我的代码这样写

class A{public:    A(){ cout << "构造" << endl; }    int a;    void * operator new(size_t size)    {        cout << "dong" << endl;        return (void *)1;    }};int test2(){    A *b = new A;    return 0;}

结果就是
这里写图片描述

为啥是这样应该都能明白吧!!

验证5:为啥说功能和malloc一模一样

class A{public:    A(){ cout << "构造" << endl; }    int a;    void * operator new(size_t size)    {        cout << "dong" << endl;        return (void *)1;    }};int test2(){    A *b = (A *)operator new (12);    A *c = (A *)malloc(12);}

看一下源码 VC/crt/src/newop.cpp

void *__CRTDECL operator new(size_t count) _THROW1(_STD bad_alloc)    {   // try to allocate size bytes    void *p;    while ((p = malloc(count)) == 0)        if (_callnewh(count) == 0)            {   // report no memory            _STD _Xbad_alloc();            }    return (p);    }

其实底层就是调用的malloc

有人会奇怪我不是重载了operator new()么?为啥不打印?
因为我们调用的是全局operator new()啊,C++编译器在全局给我们默认创建了一个
那我们怎么调用自己类中的operator new()呢?没有对象我们能调用类中的函数么?
1.没有类对象我们是可以调用类中部分函数的。
2.更何况重载了operator new()编译器会自动帮我们把这个函数改为static的,也就是静态的。
所以不管是哪一方面都是可以调用的
这里写图片描述

然后我们看一看 定位new
这里写图片描述
下面 new A 就等价于上面两句话

注意上面这幅图我没有重载operator new(),因为如果重载了,定位new的时候会发生参数不匹配问题
如果你实在想调用自定义的operator new()可以这样写

A *p = (A*)operator new(sizeof(A));A *a = new (p) A;

new的知识还是蛮多的

0 0