delete[] 是否适用于通用数组?如果是这样,为什么在其上使用 std::vector::erase 会导致释放内存时出错

Does delete[] work properly with generic arrays? If so why does using std::vector::erase on it cause error in freeing memory

我试图使用圆形数组,因此最终编写了一个 CircularArray class,我已为其附加了代码。它使用数组的通用指针。 当我尝试使用 std::vector 创建此类圆形数组的列表时,我在尝试对其使用擦除时遇到问题。

我不明白为什么会这样,因为我认为析构函数和复制构造函数正常工作得很好。

有人可以帮忙吗?

代码:
循环数组 Class

template<class T> class CircularArray
    {
        //Class denoted by 'T' is expected to have a functional assignment operator, i.e. operator=(const T& ext) {} in place
    protected:
        int size=0;
        int ori=0;
        T* array;
    private:
        int pos=0;

    public:
        CircularArray() : CircularArray(0) {}
        CircularArray(int s) {size=s;array=new T[s];}
        CircularArray(T* ptr,int s)// : CircularArray(s)
        {
            size=s;array=new T[s];
            for(int i=0;i<size;i++)
                array[i]=ptr[i];
        }
        CircularArray(const CircularArray<T>& arr) : CircularArray(arr.size)
        {
            for(int i=0;i<size;i++)
                array[i]=arr.array[i];
        }
        ~CircularArray() {delete[] array;}
        ...

测试代码

int main()
{
    std::vector<CircularArray<int>> test;
    int *a1=new int[3] {1,2,3},*a2=new int[3] {1,2,3},*a3=new int[3] {1,2,3};
    CircularArray<int> n1(a1,3),n2(a2,3),n3(a3,3);
    test.push_back(n1);
    test.push_back(n2);
    test.push_back(n3);
    test.erase(test.begin()+1);
    for(auto v : test)
    {
        for(int i=0;i<3;i++)
            cout << v[i];
        cout << "\n";
    }
}

该程序在遇到矢量的删除部分后给出了错误的输出。 Valgrind 说在尝试读取释放的内存时存在内存损坏。 怎么了?

向量元素必须 copy/move 可赋值,但您依赖默认的复制赋值运算符,它不会创建任何新内存。您分配的对象都共享相同的内存 space,稍后会导致双重释放。

你的构造函数很好,但你还需要一个 copy/move 赋值运算符。

了解 Rule of Five

也可以考虑只使用 std::vector 作为后备存储;会简单很多。

Does delete[] work properly with generic arrays?

是的。

您的(隐式生成的)复制和移动赋值运算符是错误的。他们将复制成员指针。然后你有两个指向同一个数组的指针,一个析构函数删除它一次,另一个析构函数删除它第二次,这会导致未定义的行为。

手动管理动态资源时,必须跟踪所有权,并确保它恰好被释放一次。典型的解决方案是使用智能指针。您的 class 拥有动态数组的唯一所有权(或者,如果它没有意外地共享赋值运算符的所有权,它将拥有),因此唯一指针将是一个合适的选择。

另一方面,您可以使用向量容器而不是智能指针。