`
蒙面考拉
  • 浏览: 161212 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

delete []p 和 delete p的区别

 
阅读更多

operator new 和 operator delete函数有两个重载版本,每个版本支持相关的new表达式和delete表达式:

在回收用 new 分配的单个对象的内存空间的时候用 delete,回收用 new[] 分配的一组对象的内存空间的时候用 delete[]。
关于 new[] 和 delete[],其中又分为两种情况:(1) 为基本数据类型分配和回收空间;(2) 为自定义类型分配和回收空间。

对于 (1),上面提供的程序a可以证明了 delete[] 和 delete 是等同的。
程序a:
#include <stdio.h>
#define BUFF_SIZE 10240
int main(int argc, char *argv[])
{
printf("Hello, world\n";
char* p = NULL;
while(1)
{
p = new TTT[BUFF_SIZE];
printf("0x%08XH\n",p);
Sleep(5000);
delete p; //或者delete [] p;
p = NULL;
}
return 0;
}

但是对于 (2),情况就发生了变化。请看下面的程序。
#include <stdio.h>
#define BUFF_SIZE 10240

class TTT
{
public:
TTT()
{
//aa = new char[1024];
};
~TTT()
{
//delete [] aa;
//printf("TTT destructor()\n";
};
private:
int a;
char* aa;
int inta[1024];
};

int main(int argc, char *argv[])
{
printf("Hello, world\n";
TTT* p = NULL;
while(1)
{
p = new TTT[BUFF_SIZE];
printf("0x%08XH\n",p);
delete p; //delete [] p;
p = NULL;
}
return 0;
}

大家可以自己运行这个程序,看一看 delete p1 和 delete[] p1 的不同结果,我就不在这里贴运行结果了。

从运行结果中我们可以看出,delete p 在回收空间的过程中,只有 p[0] 这个对象调用了析构函数,其它对象如 p[1]、p[2] 等都没有调用自身的析构函数,在析构函数中的内存释放操作将不会被执行(引发内存泄漏),已使用内存不断增加,这就是问题的症结所在。如果用 delete[],则在回收空间之前所有对象都会首先调用自己的析构函数,已使用内存不会不断增加。

基本类型的对象没有析构函数,所以回收基本类型组成的数组空间用 delete 和 delete[] 都是应该可以的;但是对于类对象数组,只能用 delete[]。对于 new 的单个对象,只能用 delete 不能用 delete[] 回收空间。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ssfp8762/archive/2009/11/07/4783458.aspx

 

   void* operator new (size_t);        // allocate an object
   void* operator new [] (size_t);     // allocate an array
  
   void operator delete (void*);       // free an oject
   void operator delete [] (void*);    // free an array
另外一般的教材比如《高质量C++编程指南》都会这么说:
在用delete 释放对象数组时,留意不要丢了符号‘[]’。例如
delete []objects; // 正确的用法
delete objects; // 错误的用法
后者相当于delete objects[0],漏掉了另外99 个对象
这样的描述当然是错误的,而且会误导观众

为了解决问题,打开vc6,输入以下代码:
class A
...
{
private
:
   
int
 i;
  
string
 s;
public
:
 
~A() ...{  printf("hi"); }

}
;
void d(A *
);
int   main(int   argc,   char*
   argv[]) 
...
{
 A 
*= new A[10
];
 d(p);
 
return   0

}

 
void d(A *p)
...
{
 delete p;
}


运行结果:debug assertion failed!
咦,不是说等同于delete p[0]吗?

为了看看究竟,只好动用那多年以前就忘光了的汇编
经过一番折腾,最后连猜带蒙得出下面的观点:
1 如果对象无析构函数(包括不需要合成析构函数,比如注释掉~A和string s两行代码)
delete会直接调用operator delete并直接调用free释放内存
这个时候的new=new [](仅在数量上有差异),delete=delete[]
2 如果对象存在析构函数(包括合成析构函数),则【这个才是重点】:
new []返回的地址会后移4个字节,并用那4个存放数组的大小!而new不用后移这四个字节
delete[]根据那个4个字节的值,调用指定次数的析构函数 ,同样delete也不需要那四个字节
 
结果就是在不恰当的使用delete 和delete []调用free的时候会造成4个字节的错位,最终导致debug assertion failed!
再回到《高质量C++编程指南》:
delete []objects; // 正确的用法
delete objects;  // 错误的用法
后者相当于delete objects[0],漏掉了另外99 个对象
严格应该这样说:后者相当于仅调用了objects[0]的析构函数,漏掉了调用另外99 个对象的析构函数,并且在调用之后释放内存时导致异常(如果存在析构函数的话),如果对象无析构函数该语句与delete []objects相同
总结一下:
分享到:
评论

相关推荐

    VC8.0上new/delete分析

    通过以上分析可以看出,在VC8.0中,`new` 和 `new[]` 以及 `delete` 和 `delete[]` 有着明确的区别和使用场景。正确地使用这些操作符是确保程序内存安全的关键。此外,通过深入理解这些操作符的底层实现,可以更好地...

    一个关于c++字符串处理和delete[]与delete差别的问题.docx

    然而,在某些编译器(如VC6.0和C++Builder5.0)中,作者发现`delete p`和`delete p[]`在释放动态分配的字符数组时并无区别。这可能是因为编译器内部处理了这个特殊情况,使得两者的行为相同。但需要注意的是,这不是...

    12_delete和delete[]的区别1

    然而,当涉及到对象数组时,`new[]`和`delete[]`的使用显得尤为重要,因为它们之间存在微妙的差别。 首先,`new`关键字用于为单个对象或对象数组分配内存。如果为单个对象分配内存,如`int *p = new int;`,那么...

    delete的用法

    本文将详细介绍`delete`和`delete[]`的用法及其区别,并通过示例代码帮助读者更好地理解和掌握这些概念。 #### 二、`new`与`delete` 在C++中,`new`操作符用于动态分配内存,而`delete`操作符用于释放由`new`分配的...

    C++ 使用new与delete需注意的原则

    C++的动态内存管理是通过new和delete两个操作来完成的,即用new来申请空间,用delete来释放空间。在使用new和delete时,注意以下原则。 1.new与delete需一一对应 用new操作申请空间,如果申请成功,必须在以后的某个...

    **p与 *&p的区别, 即指向指针的指针和引用指针变量的区别

    在C语言中,**p与*&p是两个常见的指针操作表达式,它们分别涉及到指向指针的指针和引用指针变量的概念。理解这两者的区别,有助于更准确地掌握指针的操作和内存管理。 首先,我们需要明确**p的含义。当声明一个指针...

    C++中delete和delete[]的区别

    `new`和`delete`操作符用于为对象分配和释放堆内存,而`new[]`和`delete[]`则用于数组分配和释放。理解它们之间的区别是避免内存泄漏和确保程序正确性的关键。 1. 单个对象的分配与释放: 当使用`new`关键字为单个...

    new,delete和指针

    "new,delete和指针" new、delete和指针是C++中的一些基本概念,它们是C++内存管理的基础。在本文中,我们将详细讲解new、delete和指针的概念和使用方法,并对它们之间的关系进行详细的解释。 首先,让我们来了解...

    C语言也能面向对象(二)——new和delete

    本文将深入探讨C++中的"new"和"delete"操作符,这是理解和掌握C++内存管理的关键。 面向对象编程(Object-Oriented Programming,简称OOP)是一种编程范式,它基于“对象”的概念,这些对象封装了数据和操作这些...

    拨开自定义operator new与operator delete的迷雾.docx

    在C++编程中,自定义`operator new`和`operator delete`是实现特定内存管理策略的重要手段。它们允许程序员根据需求调整内存分配和释放的行为。本文将深入探讨这两个操作符的自定义规则、使用场景以及潜在的陷阱。 ...

    C# 键盘钩子例子 可屏蔽Ctrl+Alt+Delete

    在C#中,我们主要依赖于P/Invoke(Platform Invoke)技术来调用Windows API函数,这些函数定义在`kernel32.dll`和`user32.dll`库中。 首先,我们需要导入必要的API函数: ```csharp using System.Runtime....

    windows下c# 屏蔽系统atrl+alt+delete组合键

    通过以上步骤,你可以使用C#编写一个控制类软件,在Windows 10和Windows 7上屏蔽Ctrl+Alt+Delete键。在BanCAD这个项目中,可能已经包含了实现这一功能的源代码和相关资源。解压BanCAD文件后,可以学习和理解其中的...

    new_delete

    【new_delete】是C++中的两个关键操作符,用于动态内存的分配和释放。它们是C++内存管理的重要组成部分,特别是在处理大型数据结构或者需要在运行时决定内存大小的情况下。 在C++中,内存分为栈内存和堆内存。栈...

    11_new&delete与malloc&free 之间的关系与区别1

    "new与delete和malloc与free之间的关系与区别" 在C++编程语言中,new和delete是C++的关键字,是一种操作符,可以被重载,而malloc和free是C语言的库函数,并且不能重载。这两对函数都是用于内存管理的,但是它们...

    关于new和delete的详细用法

    关于new和delete的详细用法 1. new是C++的一个关键字,同时也是操作符。它可以用于在堆上动态创建一个对象,实际上做了三件事:获得一块内存空间、调用构造函数、返回正确的指针。 2. new的三种形态:new operator...

    联想Y430P-刷BIOS V3.66+教程+软件

    在“联想Y430P-刷BIOS”这个压缩包中,可能包含的文件有BIOS更新程序、详细的教程文档,以及可能的安全提示和注意事项。确保在执行任何操作前,详细阅读这些文件,了解整个过程,以避免可能的风险。在进行硬件升级,...

    复习(数据结构).doc

    delete p; B. q=p-&gt;next; p- &gt;next=q-&gt;next; delet p-&gt;next; C. p-&gt;next=p-next-&gt;next; delet p-&gt;next; D. q=p-&gt;next; p- &gt;next=q-&gt;next; delete q; 4. p是指向单链表头结点的指针,若该链表是空表,下面正确的说法...

    P/L SQL基础教程

    P/L SQL与SQL的关系紧密,但有所区别。SQL*Plus是Oracle提供的一种用于连接和操作数据库的命令行工具,它可以执行SQL和P/L SQL语句,支持数据的查询、更新以及数据库管理等多种操作。而P/L SQL则是一种更强大的编程...

Global site tag (gtag.js) - Google Analytics