交换指针后删除动态分配的内存

Delete dynamically allocated memory after swapping its pointer

我是C++的新手,想同时了解内存管理和指针。

假设我有下面的代码

int* p1;
int* p2;
int* p3 = new int[some size];

p1 = p3;

std::swap(p1,p2);

如何正确删除动态分配的内存? delete[] p3 够了吗?之后我也应该删除 p2 吗?

当你这样做时,口语中有些模糊:

delete x;

我们说“删除x”。严格来说是错误的,因为删除的是x.

指向的对象

通过 new/new[] 分配的每个对象都必须通过一次调用 delete/delete[] 来销毁。无论您有两个或更多指向同一个对象的指针都不会改变这一点。

int* p1 = nullptr;
int* p2 = nullptr;
int* p3 = new int[some size];      // p3 points to the array

p1 = p3;                           // p1 points to the same array

std::swap(p1,p2);                  // now p1 == nullptr, p2 points to the array

请注意,您的示例中的指针未初始化。读取它们的值会导致未定义的行为。因为这不是问题的关键,所以我通过初始化它们来避免这个问题。

通过 new [] 创建了一个数组,您必须通过 delete [] 删除该数组。你不能删除它两次。所以要么调用 delete[] p3; 要么调用 delete[] p2;,但不能同时调用。

PS: 评论已经提到了智能指针,我也建议你阅读它们。现在你不应该使用原始拥有指针。拥有指针是您需要对其调用 delete 的指针,它“拥有”指向的对象。原始指针应该只用于“观察”,即您永远不需要担心在原始指针上调用 delete(或 delete[])。当然你还需要注意指向的对象是否还活着,但这不是动态分配所特有的:

 int* p;
 { 
     int x = 42;
     p = &x;         // p points to x;
 }                   // x goes out of scope
 // here p is not a valid pointer anymore

要了解这里发生了什么,添加一些调试语句会有所帮助,即:

std::cout << p1 << " " << p2 << " " << p3 << "\n";

跟踪将产生如下输出:

0 0 0x15e7eb0
0x15e7eb0 0 0x15e7eb0
0 0x15e7eb0 0x15e7eb0

(注意我把p1和p1初始化为nullptr)

p3 最初指向一些内存。在赋值 p1 = p3 之后,p1 现在指向与 p3 相同的内存地址。交换指针时,现在是 p2 指向与 p3 相同的内存地址。

这里有几点需要注意:

  • 必须 delete[] 与相应的 new[] 配对(不要用 new[] 调用 delete 等等)
  • 对已删除的对象调用 delete 是未定义的行为
  • 对空指针调用 delete 是绝对安全的

如您所见,处理原始指针和内存分配很容易导致陷阱。通常建议使用智能指针,或者如果您有一个非拥有指针,则使用像 observer_ptr 这样的抽象来在代码中清楚地指示指针的用途。