1

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

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[]在赋值运算符实现中使用数组(因为在构造被分配的对象期间它已经被分配到某个地方)。而且我确实认为您不需要在复制构造对象时释放数组,因为它尚未构造。

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

那么,我应该delete[] xs在复制构造函数、赋值运算符中,还是两者都没有?

4

1 回答 1

0

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

那么,我应该在复制构造函数、赋值运算符中删除[] xs,还是两者都没有?

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

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

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

另请注意,为了避免悬空指针和可能的未定义行为,您应该确保您的类确实是封装数组的唯一所有者。否则,类外部的代码可以delete[],或者保存指向它的指针,这将变得悬空。因此,您不应该将xsdata member 设为public

于 2013-03-22T10:27:51.807 回答