参考资料:

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. Git的杀手级功能之 一 远程仓库

    Git的杀手级功能之一:远程仓库 Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上. 一.注册GitHub账号,然后和本地Git仓库来关联免费获得Git远程仓库来学校git的远程仓 ...

  2. JavaScript对数组的处理(一)

    数组创建 JavaScript中创建数组有两种方式,第一种是使用 Array 构造函数: var arr1 = new Array(); //创建一个空数组 var arr2 = new Array( ...

  3. tf.variable_scope

    转载:https://blog.csdn.net/gaoyueace/article/details/79079068 例如: #在名字为ae的命名空间内创建变量 with tf.variable_s ...

  4. c++ windows下计时

    多核时代不宜再用 x86 的 RDTSC 指令测试指令周期和时间 陈硕Blog.csdn.net/Solstice 自从 Intel Pentium 加入 RDTSC 指令以来,这条指令是 micro ...

  5. UIStatusBarStyle PreferredStatusBarStyle does not work on iOS 7

    Q: In my iPhone application built with Xcode 5 for iOS 7 I set UIViewControllerBasedStatusBarAppeara ...

  6. Masonry插件:内容始终水平居中

    跟随浏览器框架大小,主题内容居中 代码 <!DOCTYPE html> <html> <head> <title>masonry瀑布流插件</ti ...

  7. ubuntu12.04 折腾流水

    今天突然间update 一些软件后,就遇到了无法启动桌面,就是输入正确的用户名和密码后还是无法进入系统. 重启后,一直停留在waiting for network configuration, 然后显 ...

  8. 使用pyinotify实现加强版的linux tail -f 命令,并且对日志类型的文本进行单独优化着色显示。

    tail -f命令不能自动切换切片文件,例如日志是每100M生成一个新文件,tail -f不能自动的切换文件,必须关闭然后重新运行tail -f 此篇使用pyinotify,检测文件更新,并实现tai ...

  9. python--内置函数---13

    原创博文,转载请标明出处--周学伟 http://www.cnblogs.com/zxouxuewei/ Python 内置函数     内置函数     abs() divmod() input() ...

  10. [Unity3D] 01 - Try Unity3D

    01. Move and Rotate 标准全局坐标系 Keyboard using UnityEngine; using System.Collections; public class NewBe ...