Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么可以';通过指针从数组中删除除第一个元素以外的其他元素_C++_Arrays_Memory Management_Memory Leaks_Heap Memory - Fatal编程技术网

C++ 为什么可以';通过指针从数组中删除除第一个元素以外的其他元素

C++ 为什么可以';通过指针从数组中删除除第一个元素以外的其他元素,c++,arrays,memory-management,memory-leaks,heap-memory,C++,Arrays,Memory Management,Memory Leaks,Heap Memory,考虑以下代码: int main() { int *intArPtr = new int[100]; int *intArPtr1 = intArPtr + 1; delete [] intArPtr; //ok //delete intArPtr; //valgrind warning, but no leaks! //delete intArPtr1; //invalid pointer error return 0; } 我知道delete[]intArPtr

考虑以下代码:

int main()
{
  int *intArPtr = new int[100];
  int *intArPtr1 = intArPtr + 1;

  delete [] intArPtr; //ok
  //delete intArPtr; //valgrind warning, but no leaks!
  //delete intArPtr1; //invalid pointer error

  return 0;
}
我知道
delete[]intArPtr
是删除此数组的唯一有效方法,但我只是好奇以下几点:

  • 为什么
    删除intArPtr
    不会产生任何内存泄漏?它是 没有定义的行为,我很幸运没有
  • 为什么
    delete intArPtr1
    会在运行时出错?为什么不先从数组中删除所有元素
  • C++的运行时如何知道所分配数组的大小(对于delete[])?它存放在什么地方了吗
  • 为什么
    删除intArPtr
    不会产生任何内存泄漏?它是 没有定义的行为,我很幸运没有
  • 正确,在使用
    new[]
    分配的内存上调用
    delete
    是未定义的行为。首先,它不会调用数组成员上的析构函数


    第二,即使您只是询问内存释放而不是对象销毁,也有可能以相同的方式实现
    delete
    delete[]
    ,或者实现方式不同。它们读起来像是同一件事,但它们不是:
    delete
    delete[]
    是两个不同的操作符,具有潜在的不同实现。他们可以使用不同的分配策略(见下面问题3的答案)

  • 为什么
    delete intArPtr1
    会在运行时出错?为什么不先从数组中删除所有元素
  • 您必须传递
    delete
    分配有
    new
    的指针。准确的指针。在
    新的
    分配的内存区域中没有一个指针,这不起作用。它必须是指向区域开始的同一指针

  • C++的运行时如何知道所分配数组的大小(对于delete[])?它存放在什么地方了吗
  • 一种常见的分配器策略是在分配的区域之前存储分配的字节数
    delete
    然后将获取您传递的指针,向左看4或8个字节,并将该整数解释为区域的大小。如果你给它一个指向其他地方的指针,它的回溯策略就会失败

    C++语言没有指定如何跟踪内存分配,所以这是一个实现细节。不同的标准库、编译器和操作系统将以不同的方式实现这一点。我所描述的只是一种可能的机制

    进一步阅读:

    • C++常见问题解答:
    • C++常见问题解答:
    答案:

  • 您的示例中没有内存泄漏。事实上,如果数组中的对象本身分配了一些内存,并且应该在析构函数中释放这些内存,那么删除不带[]的数组只会导致内存泄漏。在所有其他情况下,不正确的删除不会导致内存泄漏
  • 因为分配的内存大小存储在指针之前。当您访问数组中除第一个元素以外的任何其他元素时,没有适当的内存大小
  • 见第2条
  • 为什么删除intArPtr不会产生任何内存泄漏?这是一种未定义的行为,而我很幸运没有
  • 是和否同时出现。使用
    delete
    而不是
    delete[]
    并不干净,但通常是有效的。指针和偏移量基本上都存储在分配时。这允许在使用
    delete
    时发生适当的解除分配,即使是偶然的

  • 为什么删除intArPtr1会在运行时出错?为什么不先从数组中删除所有元素
  • intArPtr1
    与分配区域的指针不对应。当尝试删除该地址时,运行时在分配表中找不到该地址

  • C++的运行时如何知道所分配数组的大小(对于delete[])?它存放在什么地方了吗

  • 它存储在分配表中,指针指向分配的区域。

    3。是,分配数组的大小通常存储在指针之前的区域。重复:1。二,。是的,这是未定义的行为。这取决于实现——未定义的行为。这对我来说很清楚。谢谢
    delete
    delete[]
    不可能“相同地实现”。对于POD类型,调用其中一个的效果可能无法区分,但是对于包含指向被删除对象所拥有的其他分配的指针的用户定义类型,调用
    delete
    和调用
    delete[]
    之间有着深刻的区别,即使在系统上,不正确地使用它们对吊舱类型的影响也无法区分。关键问题是,
    delete
    只会为[0]处的对象调用类型的析构函数一次,而
    delete[]
    会为数组中的每个对象调用析构函数。@phonetagger:
    delete
    delete[]
    当然有可能以相同的方式实现,例如,
    新T
    的实现与
    新T[1]
    具有相同的效果。