繁体   English   中英

动态数组取消分配(赋值运算符与副本构造函数)

[英]Dynamic array deallocation (assignment operator vs. copy constructor)

我应该在复制构造函数和/或赋值运算符中释放动态数组(在构造函数中分配)吗?

struct Test
{
  const size_t n;
  int* xs;

  Test(const size_t n)
    : n(n)
    , xs(new int[n])
  { }

  Test(const Test& other)
    : n(other.n)
    , xs(new int[n])
  {
    memcpy(xs, other.xs, n * sizeof(int));
  }

  Test& operator=(const Test& other)
  {
    n = other.n;
    delete[] xs;
    xs = new int[n];
    memcpy(xs, other.xs, n * sizeof(int));
  }

  ~Test()
  {
    delete[] xs;
  }
};

void main()
{
  Test a(10);
  Test b(a);
  Test c(20);
  c = b;
}

如您所见,我猜您必须在赋值运算符实现中delete[]数组(因为在构造要分配给的对象的过程中已经将该数组分配到了某个位置)。 而且我确实认为,在复制构造对象时不需要释放数组,因为尚未构造该对象。

问题是,无论是否在operator= delete[] ,在Application Verifier下运行以上应用程序都不会显示内存泄漏。 尽管在两种情况下,应用程序都可以正常运行。

所以,我应该在复制构造函数,赋值运算符中都delete[] xs还是两者都不做?

通常,手动内存管理是一个主意。 您不应该这样做,并且您应该更喜欢std::vector<>或其他容器类,除非您有充分的理由这样做。 说...

所以,我应该在复制构造函数,赋值运算符中都删除[] xs还是两者都不做?

在丢失指向该数组的最后一个指针之前,应delete[]一个分配有new[]数组。 否则,您将泄漏。

实际上,由于您要删除的数组是由您的类拥有并封装的,因此这意味着您必须在赋值运算符重载中将delete[] (在将指针分配给新数组之前,因此将丢失唯一的现有数组)对前一个引用)和在析构函数中(当您处置该对象,然后丢失对封装数组的唯一现有引用时)。

就像您说的那样,复制构造函数是一个构造例程,并且指针先前未引用任何已分配的资源(实际上,这里没有“以前”,对象的生命期甚至还没有开始):因此,不仅这里不需要delete[] ,这是错误的。

还要注意,为了避免悬空的指针和可能的未定义行为,您应确保您的类确实是封装数组的唯一所有者。 否则,该类外部的代码可以delete[] ,或保存指向该类的指针,这些指针将变得悬而未决。 因此,您不应将xs数据成员xs public

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM