【问题标题】:What happens if one uses delete[] after a delete?如果在删除后使用 delete[] 会发生什么?
【发布时间】:2019-07-12 10:31:17
【问题描述】:

我正在尝试实现一个具有动态长度的自制矢量类。这个想法是使用指针和动态分配的空间,如下所示。

template<class T>
class myVector
{
    int size;
    T* array;
public:
    myVector(int n): size(n), array(new T[n]){}
    ~myVector(){delete[] array;}
    T pop();
    ...
}

如果我需要推送,我会创建一个新对象,其中包含一个指向新分配空间的新指针并复制整个内容。现在我卡在 pop 部分,因为我不知道如何在调用 pop() 后释放未使用的空间。

像这样在pop()中使用delete可以吗

T pop()
{
    T = *(array+size-1);
    delete array+size-1;
    return T;
}

但是如果我这样做,那么当调用析构函数时,弹出的位置会被删除两次,我认为这可能会出错。而且我知道我可以等到整个数组为空后再删除,但可能会发生一个非常大的数组首先分配并在程序运行时弹出很多,如果我可能会导致大量未使用的空间不要在中间释放它们。

我的问题:

(1) 如果我在 pop() 中写 delete 会发生什么?

(2) 我能做什么? (最好只有删除)

【问题讨论】:

  • (1) 在我的机器上,它会终止正在运行的应用程序。 (2) 永远不要使用new/delete,永远不要使用new[]/delete[]。请改用std::vectorstd::make_uniquestd::make_shared

标签: c++ memory-management dynamic-programming delete-operator


【解决方案1】:

您的代码存在严重缺陷。

首先,必须使用delete[] 删除任何new T[N]。所以你的析构函数需要使用delete[],而不是delete

然后,您不能使用delete 从缓冲区中弹出单个元素。这是未定义的行为(安全风险),因为元素尚未分配new

真正的vector处理这个问题的方式,是在堆上分配char的缓冲区,然后在缓冲区中手动调用T的构造函数和析构函数,通过使用placement new显式析构函数调用

【讨论】:

    【解决方案2】:

    你必须 deletenewdelete[]new[] 什么都没有。您不能从动态分配的数组中删除单个元素,只能删除整个元素。您当前的析构函数具有未定义行为,因为您 delete 是您使用 new[] 创建的东西。

    1) 发生未定义的行为。不要这样做。

    2) 删除整个数组并分配一个少一个元素的新数组。由于这对性能很不利(添加 N 元素具有 O(N^2) 运行时),您应该查看 std::vector 所做的大小+容量。

    【讨论】:

    • 对不起,应该是delete[]。但我的问题更多是关于 pop 而不是析构函数。而如果我想释放中间未使用的空间,我在pop()中可以做什么?
    猜你喜欢
    • 2023-03-03
    • 2019-06-28
    • 1970-01-01
    • 1970-01-01
    • 2019-07-24
    • 1970-01-01
    • 1970-01-01
    • 2016-04-14
    • 2018-02-25
    相关资源
    最近更新 更多