C++ 代码: int* aa=int a new intt[0]; delete []aa; 为什么不报错呢? 对内存的理解还不够,希望大牛给予指点

C/C++ int *p = new int[10]; 释放p的时候是要,还是delete []p;?说明为什么不是另一种。_百度知道
C/C++ int *p = new int[10]; 释放p的时候是要,还是delete []p;?说明为什么不是另一种。
我有更好的答案
如果你用 delete pdelete []p;它就只会释放 p 指向的当前空间,也就是这块内存的第一个空间,而后面的空间都没有被释放;因为你的 p 是作为一个指针
指向一片连续的内存的第一个空间
采纳率:37%
为您推荐:
其他类似问题
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。您所在的位置: &
关于new和delete 一些不得不说的事(2)
关于new和delete 一些不得不说的事(2)
new和delete在C++中作用很大,但是当你写下new和delete的时候,到底发生了什么事,你了解过吗?本文为你讲述当你写下new和delete的时候,到底发生了什么事。
那构造函数到底是谁调用的?看operator new下面的那片汇编代码:&&add&&&&&&&&&esp,4& &&&mov&&&&&&&&&dword&ptr&[ebp-0F8h],eax& &0041143D&&mov&&&&&&&&&dword&ptr&[ebp-4],0& &&&cmp&&&&&&&&&dword&ptr&[ebp-0F8h],0& &0041144B&&je&&&&&&&&&&wmain+70h&(411460h)& &0041144D&&mov&&&&&&&&&ecx,dword&ptr&[ebp-0F8h]& &&&call&&&&&&&&a::a&(41101Eh)&&
出去将返回值赋给tmp的操作,我们看到了一处函数调用:&call&a::a&(41101Eh)&&
没错,对类a的构造函数的调用,是编译器偷偷在你的函数里插入的,当时的情况就是如此。delete的情况也是一摸一样。再来看针对对象数组的new和delete:class&a &{ &public: &&a() &&{ &&&int&i1; &&&int&j1&=&0; &&&static&int&k1; &&&static&int&l1&=&0; &&&foo(); &&} &&int&foo() &&{ &&&return&0; &&} &&&~a() &&{ &&&int&i2; &&&int&j2&=&0; &&&static&int&k2; &&&static&int&l2&=&0; &&&bar(); &&} &&&int&bar() &&{ &&&return&1; &&} &}; &&int&_tmain(int&argc,&_TCHAR*&argv[]) &{ &&a*&tmp&=&new&a[10]; &&delete[]& &&return&0; &} &
反汇编之后的结果如下:int&_tmain(int&argc,&_TCHAR*&argv[]) &{ &&&push&&&&&&&&ebp&& &&&mov&&&&&&&&&ebp,esp& &&&push&&&&&&&&0FFFFFFFFh& &&&push&&&&&&&&offset&__ehhandler$_wmain&(41478Eh)& &004113FA&&mov&&&&&&&&&eax,dword&ptr&fs:[h]& &&&push&&&&&&&&eax&& &&&sub&&&&&&&&&esp,100h& &&&push&&&&&&&&ebx&& &&&push&&&&&&&&esi&& &&&push&&&&&&&&edi&& &0041140A&&lea&&&&&&&&&edi,[ebp-10Ch]& &&&mov&&&&&&&&&ecx,40h& &&&mov&&&&&&&&&eax,0CCCCCCCCh& &0041141A&&rep&stos&&&&dword&ptr&es:[edi]& &0041141C&&mov&&&&&&&&&eax,dword&ptr&[___security_cookie&(418000h)]& &&&xor&&&&&&&&&eax,ebp& &&&push&&&&&&&&eax&& &&&lea&&&&&&&&&eax,[ebp-0Ch]& &&&mov&&&&&&&&&dword&ptr&fs:[h],eax& &&a*&tmp&=&new&a[10]; &0041142D&&push&&&&&&&&0Eh&& &0041142F&&call&&&&&&&&operator&new&(4111A4h)& &&&add&&&&&&&&&esp,4& &&&mov&&&&&&&&&dword&ptr&[ebp-0F8h],eax& &0041143D&&mov&&&&&&&&&dword&ptr&[ebp-4],0& &&&cmp&&&&&&&&&dword&ptr&[ebp-0F8h],0& &0041144B&&je&&&&&&&&&&wmain+97h&(411487h)& &0041144D&&mov&&&&&&&&&eax,dword&ptr&[ebp-0F8h]& &&&mov&&&&&&&&&dword&ptr&[eax],0Ah& &&&push&&&&&&&&offset&a::`scalar&deleting&destructor'&(41100Ah)& &0041145E&&push&&&&&&&&offset&a::a&(41101Eh)& &&&push&&&&&&&&0Ah&& &&&push&&&&&&&&1&&&& &&&mov&&&&&&&&&ecx,dword&ptr&[ebp-0F8h]& &0041146D&&add&&&&&&&&&ecx,4& &&&push&&&&&&&&ecx&& &&&call&&&&&&&&`eh&vector&constructor&iterator'&(4111F9h)& &&&mov&&&&&&&&&edx,dword&ptr&[ebp-0F8h]& &0041147C&&add&&&&&&&&&edx,4& &0041147F&&mov&&&&&&&&&dword&ptr&[ebp-10Ch],edx& &&&jmp&&&&&&&&&wmain+0A1h&(411491h)& &&&mov&&&&&&&&&dword&ptr&[ebp-10Ch],0& &&&mov&&&&&&&&&eax,dword&ptr&[ebp-10Ch]& &&&mov&&&&&&&&&dword&ptr&[ebp-104h],eax& &0041149D&&mov&&&&&&&&&dword&ptr&[ebp-4],0FFFFFFFFh& &&&mov&&&&&&&&&ecx,dword&ptr&[ebp-104h]& &004114AA&&mov&&&&&&&&&dword&ptr&[ebp-14h],ecx& &&delete[]& &004114AD&&mov&&&&&&&&&eax,dword&ptr&[ebp-14h]& &&&mov&&&&&&&&&dword&ptr&[ebp-0E0h],eax& &&&mov&&&&&&&&&ecx,dword&ptr&[ebp-0E0h]& &004114BC&&mov&&&&&&&&&dword&ptr&[ebp-0ECh],ecx& &&&cmp&&&&&&&&&dword&ptr&[ebp-0ECh],0& &&&je&&&&&&&&&&wmain+0F0h&(4114E0h)& &004114CB&&push&&&&&&&&3&&&& &004114CD&&mov&&&&&&&&&ecx,dword&ptr&[ebp-0ECh]& &&&call&&&&&&&&a::`vector&deleting&destructor'&(4111F4h)& &&&mov&&&&&&&&&dword&ptr&[ebp-10Ch],eax& &004114DE&&jmp&&&&&&&&&wmain+0FAh&(4114EAh)& &&&mov&&&&&&&&&dword&ptr&[ebp-10Ch],0& &&return&0; &004114EA&&xor&&&&&&&&&eax,eax& &} &004114EC&&mov&&&&&&&&&ecx,dword&ptr&[ebp-0Ch]& &004114EF&&mov&&&&&&&&&dword&ptr&fs:[0],ecx& &&&pop&&&&&&&&&ecx&& &&&pop&&&&&&&&&edi&& &&&pop&&&&&&&&&esi&& &&&pop&&&&&&&&&ebx&& &004114FA&&add&&&&&&&&&esp,10Ch& &&&cmp&&&&&&&&&ebp,esp& &&&call&&&&&&&&@ILT+345(__RTC_CheckEsp)&(41115Eh)& &&&mov&&&&&&&&&esp,ebp& &&&pop&&&&&&&&&ebp&& &0041150A&&ret&&&&&&&&& &&&
其他部分都大同小异,关键的不同在编译器插入的,用于初始化的代码:&&push&&&&&&&&offset&a::`scalar&deleting&destructor'&(41100Ah)& &0041145E&&push&&&&&&&&offset&a::a&(41101Eh)& &&&push&&&&&&&&0Ah&& &&&push&&&&&&&&1&&&& &&&mov&&&&&&&&&ecx,dword&ptr&[ebp-0F8h]& &0041146D&&add&&&&&&&&&ecx,4& &&&push&&&&&&&&ecx&& &&&call&&&&&&&&`eh&vector&constructor&iterator'&(4111F9h)&
我们看到数组大小0Ah,构造函数的地址41101Eh都被压入栈中,作为某函数的参数。到底是什么函数呢?就是:&&call&&&&&&&&`eh&vector&constructor&iterator'&(4111F9h)&
一个名为`eh vector constructor iterator' 的函数。我们还注意到a类的析构函数的地址也被当成参数传入,这是干什么用的呢?构造函数里为什么要析构函数的地址?比如在遍历调用构造函数的过程中,前8个都是没问题的,到第9个突然资源不足调用失败了,那么在返回前无论如何也要先把前8个的析构函数调用一遍,防止资源泄露。
delete[]的过程也大同小异,不过一个很有趣的地方是,“vector deleting destructor'”是a类的成员函数,而与‘eh vector constructor iterator’对应的`eh vector destructor iterator'函数在“vector deleting destructor'”函数内部:004134AD&&call&&&&&&&&`eh&vector&destructor&iterator'&(411203h)&&
。。。&&call&&&&&&&&operator&delete&(4110A0h)&
回收内存的操作,也在a::`vector deleting destructor'里。
【编辑推荐】
【责任编辑: TEL:(010)】
内容导航&第 1 页: &第 2 页:
关于的更多文章
AngularJS是很多Web开发人员在打造单页面应用程序时的首选创建方
随着云计算、物联网、大数据、移动互联网的大发展,你应该知道这些。
讲师: 38人学习过讲师: 1479人学习过讲师: 19人学习过
你想知道618大促都有哪些技术支撑吗?你想知道京东白
前几天和长辈闲聊之下,“大数据”,竟然也从老人家嘴
刚刚走出校园,打算在求职市场上一展英姿?各位年轻的
本书专门根据SUN官方的SCSA for Solaris 9&10考试大纲撰写而成,全面覆盖了SCSA for Solaris 9/10的认证考点,除此之外本书还有
51CTO旗下网站C++中new与delete的用法
最近在学习C++的过程中,发现指针以及new和delete的使用遍布全书,可见其重要性。在学习了一个阶段之后,总结一下new和delete的用法,指针还没有摸透,待日后总结。
1.new和delete有什么用?
new和delete是C++中的两个操作符,new用于给单个对象或者数组,结构等分配内存,在内存使用完后,用delete进行释放内存。而且是一一对应关系,有了new分配了内存,必然需要delete来释放内存,其分配和释放的必须是同一地址的内存。不然就很有可能导致内存泄漏的后果,如果内存泄漏严重,程序就极有可能崩溃。
2.使用new创建动态数组
在这里顺便介绍三个术语:
(1)联编(binding):联编是指一个计算机程序自身彼此关联(使一个源程序经过编译、连接,成为一个可执行程序)的过程,在这个联编过程中,需要确定程序中的操作调用(函数调用)与执行该操作(函数)的代码段之间的映射关系,按照联编所进行的阶段不同,可分为静态联编和动态联编。
(2)静态联编(static binding):是指在编译阶段就将函数实现和函数调用关联起来,因此静态联编也叫早绑定,在编译阶段就必须了解所有的函数或模块执行所需要检测的信息,它对函数的选择是基于指向对象的指针(或者引用)的类型。
(3)动态联编(dynamic binding):指在程序执行的时候才将函数实现和函数调用关联,因此也叫运行时绑定或者晚绑定,动态联编对函数的选择不是基于指针或者引用,而是基于对象类型,不同的对象类型将做出不同的编译结果。
然后我们假设需要编写一个程序,其中需要的数组长度无法在编译时进行确定,而需要在运行时期确定其中的值,这样就无法通过声明一个数组满足需求了。因为声明数组后,程序在编译期间将会为它分配内存,无论程序最终是否使用过数组,这个数组都占用了一定的内存,而且它不够灵活。所以在这种情况下,我们就需要使用动态联编。也是用使用new创建动态数组,在运行时分配内存。
代码实例:
int main()
int * point = new int[3];
//int * point[3] =
//This is a wrong way to difine a array
point[0] = 1;
point[1] = 2;
point[2] = 3;
cout << "point[0] is " << point[0] << "\n";
cout << "point[1] is " << point[1] << "\n";
cout << "point[2] is " << point[2] <<
//endl is equal to
delete [] //free memory
这段代码简单易懂,但凡有点基础的人应该都能看懂。其中最关键的两句无非就是new分配内存和delete释放内存的语句。new表达式分配了一个含有三个元素的数组,并且指针指向数组第一个元素,数组名此时表示数组第一个元素的地址。
3.使用new创建动态结构
创建动态结构和创建动态数组的方式和思想并没有太大的出入。直接上实例,在代码中分析。
struct struct1
//structure definition
char name[20];
int main()
struct1 * ps = new struct1;
//allot memory for structure
cout <name,20);
cout <> (*ps).
//method 2 for memory access
cout <> ps ->
cout << "Name: " << (*ps).name <<
cout << "Volume: " <volume << " cubic feet\n";
//method 1
cout << "Price: $" <price <<
//method 2
}简单说几点和创建动态数组的不同之处:
创建数组时的指针类型可以根据需求不同可以是int,char,double等等,创建结构时指针类型就只能是结构变量了,也就是上述代码中的struct1,不能任意的喜欢那个类型就上哪个了。指针方面的不同就不分析了
对于创建数组,分配内存和释放内存时都有一个[],但是在结构中,就没有这个[]了。
4.使用new创建单个对象
动态创建对象时,只需指定其数据类型,不必为该对象命名,new表达式返回指向新创建对象的指针,我们通过该指针来访问此对象。
int main()
int nights = 1001;
int * pt =
//allocate space for an int
*pt = 1001;
//store a value there
cout << "nights value = ";
cout << nights << ": location " << &nights <<
cout << "int ";
cout << "value = " << *pt << ": location
= " << pt <<
double * pd =
//allocate space for a double
//store a value there
cout << "double ";
cout << "value = " << *pd << ": location = " << pd <<
cout << "location of pointer pd: " << &pd <<
cout << ": size of * pt = " << sizeof(*pt) <<
cout << "size of pd = " <<
cout << ": size of *pd = " << sizeof(*pd) <<
}最后简单提一下这段代码中的nights变量和pd指针的&#20540;都存放在栈(stack)中,而用new分配的内存在堆(heap)或者自由存储区(free store)中。C++ 代码: int* aa=new int[0]; delete [] 为什么不报错呢? 对内存的理解还不够,希望大牛给予指点_百度知道
C++ 代码: int* aa=new int[0]; delete [] 为什么不报错呢? 对内存的理解还不够,希望大牛给予指点
我有更好的答案
编译器报错: error C2233c++是不允许定义长度为0的数组的, 如果定义 char sz[0],
当修改数据时就会导致内存被破坏: “Target of operator new()” : 包含大小为零的数组的对象数组是非法的.但是在new一个长度为0数组时,编译不报错,
也返回一个正常的指针地址,
但是实际没有分配内存
采纳率:91%
来自团队:
为您推荐:
&#xe675;换一换
回答问题,赢新手礼包&#xe6b9;
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。> 博客详情
在上篇 &&&中,讲到自定义对象在delete和delete []之间的区别,并且在VS报错的情况。 先讲一下delete和delete[] 的区别: 有个例子:
class CustomTest { public: CustomTest() { a = 0; cout&&"CustomTest 构造"&&a&& } ~CustomTest() { cout&&"Custom 析构~"&&a&& } public: };
测试程序:
void NewDeleteTest() { CustomTest* pBuf = NULL; int nTestCount = 5; pBuf = new CustomTest[nTestCount]; //init pBuf for (int i = 0; i & nTestC i++) { pBuf[i].a =i; cout&&"a = "&&pBuf[i].a&& } CustomTest *pTest = pBuf+2; cout&&"pTest a = "&&pTest-&a&& delete []pB //delete pBuf //区别就在这个地方--------------------------------------- pBuf = NULL; }
若使用的是delete pBuf,结果为:
若使用的是delete []pBuf ,结果为:
可以看到: 用delete,只是释放了一个Custom对象,但是数组中有五个对象, 用delete[], 五个Custom对象都释放了。 注:这个是用的codeBlock IDE, MinGW编译器,用它是因为不报错,好看结果,嘿嘿。 这边了解了一个基本问题,就是对于指向对象数组的指针,用delete,只会删除数组的第一个元素。 用delete[] 会将数组中的对象都释放掉。
好,现在讨论在VS下用delete删除一个对象数组指针时报错的问题。 根据报错,我们会跟到一个dbgdel.cpp文件中, /* verify block type */ _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead-&nBlockUse));
先看一个数据结构定义:就是DEBUG下系统对内存进行管理的一个数据结构:
_CrtMemBlockHeader * pH typedef struct _CrtMemBlockHeader { struct _CrtMemBlockHeader * pBlockHeaderN struct _CrtMemBlockHeader * pBlockHeaderP char * szFileN int nL #ifdef _WIN64 /* These items are reversed on Win64 to eliminate gaps in the struct * and ensure that sizeof(struct)%16 == 0, so 16-byte alignment is * maintained in the debug heap. */ int nBlockU size_t nDataS #else /* _WIN64 */ size_t nDataS int nBlockU #endif /* _WIN64 */ long lR unsigned char gap[nNoMansLandSize]; /* followed by: * unsigned char data[nDataSize]; * unsigned char anotherGap[nNoMansLandSize]; */ } _CrtMemBlockH 可以看出来,这是一个双向的链表,(每一个结构中都包含一个pre和next指针)。 还包含如下信息: 申请空间的文件名、所在行数、用户申请的数据大小, 内存块的类型,用于内存管理信息的额外空间。 现在来看出错的断言:
/* verify block type */ _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead-&nBlockUse)); 我们传进去的参数, pHead-&nBlockUse的值为147 看看是如何判断一个内存块的是否是合法的。 #define _BLOCK_TYPE_IS_VALID(use) (_BLOCK_TYPE(use) == _CLIENT_BLOCK || \ (use) == _NORMAL_BLOCK || \ _BLOCK_TYPE(use) == _CRT_BLOCK || \ (use) == _IGNORE_BLOCK)
而BLOCK_TYPE(use)又是怎么的宏定义呢:
#define _BLOCK_TYPE(block)
(block & 0xFFFF)
我们的参数穿进去之后,还是147啊。 而
CLIENT_BLOCK
NORMAL_BLOCK
IGNORE_BLOCK
没一个条件能成立,所以断言不成立,系统就会弹出那么大的错误提示框。
但是为什么我们穿进去的参数会是147呢。这个我还要好好想想,哈哈
”在线下联结了各位 OSCer,推广开源项目和理念,很荣幸有你的参与~
领取条件:参与过开源中国“源创会”的 OSCer 可以领取
这个不一定会出问题,在codeblock中用mingw编译器,在上文中提到的问题,在mingw中并没有出现。
支付宝支付
微信扫码支付
打赏金额: ¥
已支付成功
打赏金额: ¥

我要回帖

更多关于 int aa 3 3 的文章

 

随机推荐