参考资料:

http://en.cppreference.com/w/cpp/memory/new/operator_new

http://en.cppreference.com/w/cpp/memory/new/operator_delete

http://www.wuzesheng.com/?p=840

http://www.blogjava.net/bacoo/archive/2008/07/13/214612.html

#include <cstdio>
#include <cstdlib> void * operator new(size_t unSize)
{
printf("operator new called\n");
return malloc(unSize);
}
void * operator new[](size_t unSize)
{
printf("operator [] called\n");
return malloc(unSize);
} void * operator new(size_t unSize, int nLine, const char * pFunc)
{
printf("operator new called, line: %d, func: %s\n",
nLine, pFunc);
return malloc(unSize);
}
//注意:c++14才支持全局delete或delete【】有多个参数,参看参考资料2.下面两个delete不会覆盖全局的。
void operator delete(void * pMem,size_t unSize)
{
printf("delete1: %u\n", unSize);
free(pMem);
}
void operator delete[](void * pMem, size_t unSize)
{
printf("delete[]: %u\n", unSize);
free(pMem);
} class A
{
public: A(int a = ) :
_a(a)
{
printf("constructor called\n");
}
virtual ~A()
{
printf("~A()\n");
}
void * operator new(size_t unSize)
{
printf(" calledA\n");
return malloc(unSize); }
//注意:但是支持自定义类型操作符new或delete重载支持size_t参数。即要删除对象的大小delete,要删除对象数组大小delete[].。
void operator delete(void * pMem, size_t unSize)
{
printf("delete2: %u\n", unSize);
free(pMem);
}
void operator delete[](void * pMem, size_t unSize)
{
printf("delete[]: %u\n", unSize);
free(pMem);
} private: int _a;
}; class B: public A
{
public:
//隐式的为静态函数。
void * operator new(size_t unSize, int nLine, const char * pFunc)
{
printf("operator new called, line: %d, fileB: %s\n",
nLine, pFunc);
printf("operator new: %u\n", unSize);
//_b=0;
return malloc(unSize);
} ~B()
{
printf("~B()\n");
} int _b; int _bb;
}; int main()
{
A * pA = new A();
printf("#######\n"); A * pB = new (__LINE__, __FILE__) B();
printf("#######\n"); A * szA = new A[];
B *szB = new B[];
printf("#######\n"); delete pA;
printf("#######\n"); delete pB;
printf("#######\n"); delete [] szA;
printf("#######\n"); delete [] szB;
printf("#######\n");

//下面两个不是自定义类,没有类重载new.delete故只能调用全局的,本程序全局不支持size_t参数,故只能调用标准C++中的全局operate delete.故不会打印信息。
char * pC = new char[];
delete [] pC;

char *pu = NULL;
delete pu;
}

gcc下运行结果:

 calledA
constructor called
#######
operator new called,
operator new:
constructor called
#######
operator [] called
constructor called
constructor called
constructor called
constructor called
constructor called
constructor called
constructor called
constructor called
constructor called
constructor called
operator [] called
constructor called
constructor called
constructor called
constructor called
constructor called
constructor called
constructor called
constructor called
constructor called
constructor called
#######
~A()
delete2:
#######
~B()
~A()
delete2:
#######
~A()
~A()
~A()
~A()
~A()
~A()
~A()
~A()
~A()
~A()
delete[]: 84//注意84=4+8*10,数组分配的堆空间,第一个int空间放数组个数,接下来顺序放对象
#######
~B()
~A()
~B()
~A()
~B()
~A()
~B()
~A()
~B()
~A()
~B()
~A()
~B()
~A()
~B()
~A()
~B()
~A()
~B()
~A()
delete[]:
#######
operator [] called //调用覆盖的全局函数operate new [],打印信息。
//delete[]调用全局的。

说明:1 在vs中类中delete[]的size_t是8和16.不同编译器结果不同。理论上应该是数组大小*类型字节。

2 如果基类有virtual析构函数,则传给operator delete的大小讲个怒被删除指针所指对象的动态类型而变化,如果没有声明为virtual,那么通过基类指针删除指向派生类对象,大小为基类大小。

总结:

1 malloc只是C函数,内部应该是使用类似deepalloc等,主要功能是分配原始内存,返回void*类型,需要显示转换为对应对象 类型指针。没有调用对象构造函数。C中函数本来就没有类没有构造函数。

free释放回收堆空间。

2 C++中的new 和delete是操作符,A * pA = new A()分别调用下面两步:

先调用void * operator new(size_t unSize) (调用顺序:那个有就调用那个:类中重载了就调用类的,然后全局重载,最后是C++源码中的全局函数)分配原始内存,未初始化的。里面可以调用malloc或者类似deapalloc来分配内存。

在调用A的构造函数,用初始化参数初始化。

delete pA;也分两步:

先调用A析构函数;

在调用void operator delete(void * pMem)(调用顺序同上面operator new),释放内存。可调用free实现或者其他实现。

3 operator new,operator delete隐式静态函数,写不写static都是静态的。

为什么必须是静态的呢?因为他们要么在构造对象前使用要么在析构后使用。属于类的函数,不是对象的函数。

4 operator new中传入的大小是怎么获得的呢,我觉得类似于sizeof(类型名)

关于sizeof不需要实例对象,我觉得类为实例化编译器不会给成员变量分配空间,但应该有个地方放的声明,标明变量类型等。

还有,sizeof大小不包括静态成员变量,静态变量一般放在静态区,不属于对象。没有成员变量的类大小为1,有虚函数就要多4个字节(虚函数表指针)。

最后小结一下,new 和delete都是内建的操作符,语言本身所固定了,无法重新定制。但它所调用的内存分配/释放的函数,即operator new和operator delete可以被重载

ps:

从汇编代码可看出:对单个堆对象调用delete和对堆对象数组调用delete[]可以发现,两种情况最主要的差别是在调用析构代理函数时传递的对象首地址,用delete析构单个对象是传进的堆空间首地址(也是堆对象首地址),而用delete[]析构对象数组时传递的是偏移堆空间首地址4byte处内存地址(即堆空间中第一个对象首地址,前四个字节是个int型,放的数组大小,即对象个数)。因此,在释放单个对象时调用delete[],或者释放对象数组时调用delete,都会造成错误,应该配对使用。

C++ 操作符new和delete的更多相关文章

  1. C++ 内存分配操作符new和delete详解

    重载new和delete 首先借用C++ Primer 5e的一个例子: string *sp = new string("a value"); ]; 这其实进行了以下三步操作: ...

  2. new和delete操作符

    C 语言中提供了 malloc 和 free 两个系统函数, 完成对堆内存的申请和释放.而 C++则提供了两个操作符 new 和 delete. 1. newnew 分配内存空间时,  分配内存空间大 ...

  3. 动态内存分配(new)和释放(delete)

    在之前我们所写过的程序中,所必需的内存空间的大小都是在程序执行之前就已经确定了.但如果我们需要内存大小为一个变量,其数值只有在程序运行时 (runtime)才能确定,例如有些情况下我们需要根据用户输入 ...

  4. 详解new/delete(整合)

    C++中内存的动态分配与管理永远是一个让C++开发者头痛的问题,本文通过对C++中内存的动态分配释放的基本原理的介绍,让读者朋友能对C++中的内存的动态分配与释放有较为深入的理解,从而更好驾驭C++程 ...

  5. C++ delete 和 delete []

    C++ delete 和 delete [] 简单结论: new delete new [] delete []   文章 : 对 delete [] 的声明 void operator delete ...

  6. C# new关键字和对象类型转换(双括号、is操作符、as操作符)

    一.new关键字 CLR要求所有的对象都通过new来创建,代码如下: Object obj=new Object(); 以下是new操作符做的事情 1.计算类型及其所有基类型(一直到System.Ob ...

  7. C++ 中 new 操作符内幕:new operator、operator new、placement new

    一.new 操作符(new operator) 人们有时好像喜欢有益使C++语言的术语难以理解.比方说new操作符(new operator)和operator new的差别. 当你写这种代码: st ...

  8. 浅谈Javascript中的void操作符

    由于JS表达式偏啰嗦,于是最近便开始采用Coffeescript来减轻负担.举个栗子,当我想取屋子里的第一条dog时,首先要判断house对象是否存在,然后再判断house.dogs是否存在,最后取h ...

  9. C++重载操作符operator

    operator是C++关键字,用于对C++进行扩展: 1.可以被重载的操作符:new,new[],delete,delete[],+,-,*,/,%,^,&,|,~,!,=,<,> ...

随机推荐

  1. 阿里云Redis开发规范[转]

    一.键值设计 1. key名设计 (1)[建议]: 可读性和可管理性 以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如业务名:表名:id ugc:video:1 (2)[建议]:简洁性 ...

  2. 分布式缓存系统 Memcached 整体架构

    分布式缓存系统 Memcached整体架构 Memcached经验分享[架构方向] Memcached 及 Redis 架构分析和比较

  3. xshell,putty远程连接Linux并使用密钥认证

    putty秘钥登录 1.软件:putty.puttygen puttygen点击Generate生成公钥和私钥 二次保障,输入设置密码 点击保存私钥文件即可. 将公钥保存到服务器上: mkdir /r ...

  4. kafka_2.10-0.8.1.1.tgz的1或3节点集群的下载、安装和配置(图文详细教程)绝对干货

    运行kafka ,需要依赖 zookeeper,你可以使用已有的 zookeeper 集群或者利用 kafka自带的zookeeper. 单机模式,用的是kafka自带的zookeeper, 分布式模 ...

  5. Java编程思想学习笔记——访问权限修饰词

    几种访问权限修饰词 public,protected,private,friendly(Java中并无该修饰词,即包访问权限,不提供任何访问修饰词) 使用时,放置在类中成员(域或方法)的定义之前的,仅 ...

  6. Oracle-10.2.0.1,打补丁10.2.0.5:在 debian 版本4【不含4】以上,及 ubuntu 7.04【不含7.04】以上都可以安装!

    如题. todo 特殊的:ubuntu 16.04 LTS 版本 无法安装成功,原因待查找!!! 最近测试练习安装linux x64上的 oracle10.2.0.5, 都要吐了.

  7. crontab修改默认编辑器

    crontab默认编辑器为nano 修改crontab默认编辑器为vi或者其他的编辑器 可以用命令select-editor修改 改为3或者4 再用crontab -e 就是vim打开了

  8. Android 安全提示 笔记

    http://developer.android.com/training/articles/security-tips.html1.数据存储内部存储internal storage存储的数据,只能由 ...

  9. feign的callback设定后,项目启动错误

    错误如下: Error starting ApplicationContext. To display the auto-configuration report re-run your applic ...

  10. 标准JSON格式定义与解析注意点

    标准JSON格式定义与解析注意点 在JS.IOS.Android中都内置了JSON的序列化.反序列化SDK.JEE中也可以使用第三方的JSON解析库,如GSON.虽然在JSON格式被定义出来的时候并没 ...