Ali*_*232 1 c++ arrays delete-operator
它困扰着我delete []实际上做了什么,所以我只是尝试了一些代码,我对结果感到震惊
测试#1:
int main()
{
int *d;
while(true)
{
d = new int[10];
delete []d;
}
}
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,程序根本不消耗任何内存.
测试#2:
int main()
{
int *d;
while(true)
{
d = new int[10];
delete [](d + 5);
}
}
Run Code Online (Sandbox Code Playgroud)
虽然在每个循环中应该至少有20个字节(对于它保留在数组开头的五个整数)保留但未删除此程序也不消耗任何内存!
测试#3:
int main()
{
int *d;
while(true)
{
d = new int[10];
delete []d;
*d=1;
}
}
Run Code Online (Sandbox Code Playgroud)
这个导致访问违规按预期进行(似乎所有内存都被删除delete []d).
测试#4:
int main()
{
int *d;
while(true)
{
d = new int[10];
delete [](d+5);
*d=1;
}
}
Run Code Online (Sandbox Code Playgroud)
这个是最令人惊讶的,虽然while不消耗任何内存,程序也不会产生任何访问冲突,我只是想知道*d在哪里存储它的数据?
(顺便说一下,所有程序都是使用无优化编译的!)
现在主要问题是:
如果我分配了一个数组而且我已经完成了一半的工作,那么我是不是有机会释放那一半并保留另一半?
它困扰着我什么
delete []实际做
你不应该担心delete[]实际上会做什么.对于所有意图和目的而言,它是一个黑盒子,其中包含有关如何正确使用它的某些规则.您需要担心实际需要做的唯一一次是编写编译器或C++运行时(例如操作系统等)
关于那些"如何正确使用它的某些规则",测试#2和#4调用未定义的行为:
ISO C++ 2003标准5.3.5删除[expr.delete]
1 delete-expression运算符销毁由new-expression创建的派生程度最高的对象(1.8)或数组.
delete-expression:
::opt delete cast-expression
::opt delete [ ] cast-expression
Run Code Online (Sandbox Code Playgroud)
第一种方法是非数组对象,第二种方法是数组.操作数应具有指针类型,或具有指针类型的单个转换函数(12.3.2)的类类型.结果类型为void.
2如果操作数具有类类型,则通过调用上述转换函数将操作数转换为指针类型,并使用转换后的操作数代替本节其余部分的原始操作数.在任一替代方案中,如果delete的操作数的值是空指针,则操作无效.在第一个替代(删除对象)中,delete的操作数的值应该是指向非数组对象的指针或指向表示这种对象的基类的子对象(1.8)的指针(第10节).如果不是,则行为未定义. 在第二种方法(删除数组)中,delete的操作数的值应该是由前一个数组new-expression产生的指针值.如果不是,则行为未定义.[注意:这意味着delete-expression的语法必须与new分配的对象的类型匹配,而不是new-expression的语法.]
"未定义的行为"意味着任何事情都可能发生,包括您刚才描述的行为.
测试#2和#4中的这些表达式违反了5.3.5/2并将导致未定义的行为(测试#3也会导致未定义的行为,但原因不同).
d = new int[10];
delete [](d + 5);
Run Code Online (Sandbox Code Playgroud)
该delete[]行违反了5.3.5/2,因为您传递给的指针值与您delete[]给出的值不同new int[].
因此,如果new int[]命令给你0xA01D2CE9和你传递0xA01D2CE9 + 5给delete[],你不可能推理或预测会发生什么,因为你已经打破了语言的规则.实际发生的将取决于编译器和/或操作系统如何处理new[]和delete[].这可以是从没有错误发生到完全崩溃你的系统,以及介于两者之间的任何地方.
换句话说,就是不要写像delete [](d + 5);.