调用 delete[] 会破坏我的 C++ 程序

Calling delete[] breaks my C++ program

更新:感谢您的快速回复。看来我发布了旧版本的代码。除了参数化构造函数之外,一切都保持不变。如您所见,代码中存在一些缺陷,但请记住,我还没有完全完成这个。目前我更担心数组,因为这是昨天介绍的新概念。 我尝试了几种不同的方法并研究了几个小时。大多数回复说只使用向量 class 但这是为了帮助我们理解内存分配和动态数组的家庭作业。目前这是给我带来问题的 .cpp 和 .h 文件。每次触发删除(或清除函数)操作时,都会发生错误,指出 blahblah.exe 已触发断点。

MyVector.h

#pragma once

class MyVector
{
private:
    int arraySize; 
    int arrayCapacity;
    int* theData;
    void grow();

public:
    MyVector();
    MyVector(int n);
    int size() const;
    int capacity() const;
    void clear();
    void push_back(int n);
    int& at(int n);
    ~MyVector();
};

MyVector.cpp

   #include "MyVector.h"
    #include <iostream>
    using namespace std;

    MyVector::MyVector()
    {
    arraySize = 0;
    arrayCapacity = 0; 
    theData = new int[0];
    }
    MyVector::MyVector(int capacityIn)
    {
    theData = new int [capacityIn];
    arraySize = 0;
    arrayCapacity = 0;
    }
    int MyVector::size() const
    {
    return arraySize;
    }
    int MyVector::capacity() const
    {
    return arrayCapacity;
    }
    void MyVector::clear()
    {
        delete [] theData;
        theData = nullptr;
    }
    void MyVector::push_back(int n)
    {
        if (arrayCapacity==0)
        {
        arrayCapacity++;
        MyVector(arrayCapacity);
    }
    if (arraySize == arrayCapacity)
    {
        grow();
        MyVector(arrayCapacity);
    }
    theData[arraySize] = n;
    arraySize++;
}
int& MyVector::at(int index)
{
    if (index >= 0 && index<arraySize)
    {
        return (theData[index]);
    }
    else
    {
        throw index;
    }
}
void MyVector::grow()
{
    arrayCapacity = arrayCapacity + arrayCapacity;
}

MyVector::~MyVector()
{
    if (theData != nullptr)
    {
        clear();
    }
}

这里:

MyVector::MyVector(int capacityIn)
{
  int* theData = new int [capacityIn];
}

您声明了一个局部指针 theData,它隐藏了当前对象的 theData 数据成员,使其未初始化。从那里开始,所有关于使用它的赌注都被取消了,它是你的程序最终崩溃的 delete[] 纯属偶然。写入

MyVector::MyVector(int capacityIn)
{
  theData = new int [capacityIn];
}

相反,arraySizearrayCapacity 也必须初始化。

除此之外,您将运行遇到

的问题
MyVector(arrayCapacity);

push_back 函数中分配了一个 MyVector 类型的临时对象,该对象(几乎)立即再次被销毁;它不会更改当前对象。

你有很多问题我已经看到了:

  1. 您不应该像这样显式调用构造函数。它不会按照你的想法去做。将分配放在真正的成员函数中。
  2. 每次你 "grow" 你的数组,你只是分配新的,导致泄漏,因为以前的指针没有被删除。
  3. 您要问的主要问题:您甚至没有存储在构造函数中分配的指针。将 int* theData = new int [capacityIn]; 更改为 theData = new int [capacityIn];。例如,您在第一个构造函数中做得正确。
  4. 您没有在第二个构造函数 (MyVector(int)) 中初始化 arraySizearrayCapacity

吹毛求疵:

  1. 删除前无需检查 nullptr
  2. 没必要new int[0]。您永远不应该访问内存,因此只需将其初始化为 nullptr.

这导致您无法解决问题:

int* theData = new int [capacityIn];

你说的是:"Please define an integer pointer..."等等。成员变量不同于您在方法中定义的变量;这样做是没有意义的。相反,你应该这样做:

theData = new int [capacityIn];

或者,仅出于教育目的(并且为了让您理解我们正在分配给成员变量):

this->theData = new int [capacityIn];

另外(有些点可能不是那么重要,但因为你是新人,我想指出一下):

  1. 请在第二个构造函数中设置您的其他变量,您似乎忘记这样做了。

    MyVector::MyVector(int capacityIn)
    {
        theData = new int [capacityIn];
        arraySize = capacityIn;
        arrayCapacity = capacityIn;
    }
    
  2. 你应该有有意义的名字,theData是你绝对应该避免的。 http://petdance.com/2012/04/the-worlds-two-worst-variable-names/

  3. 您的方法应以动词开头,例如getDimension() getCapacity() 等等。
  4. 构造函数是...构造函数,这意味着只要项目构造就会调用它们]创建。您绝对不应该以任何方式显式调用构造函数。
  5. 这是一个基本规则:无论何时使用 new 命令访问内存,都应该在一段时间后在某处调用 delete。您的代码存在严重的内存泄漏。

我可能可以为您提供更多帮助,但我不完全理解您在某些方法中想要完成的工作,即 grow()pushBack()

在构造函数体内通过赋值语句来初始化变量不是好的风格。相反,应该在进入构造函数主体之前初始化变量。

您可以使用 member initializer list 或在 class 定义中提供默认值来执行此操作。后者在这里似乎最简单:

class MyVector
{
private:
    int arraySize = 0;
    int arrayCapacity = 0;
    int* theData = nullptr;
    // ....

在构造函数中,您应该利用现有函数来做同样的事情,而不是复制代码:

MyVector::MyVector(int capacityIn)
{
     // call function which increases capacity to match capacityIn.
}

目前您实际上没有增加容量的功能,因此您需要添加一个。 (grow() 函数使 int 变量增加,但您不会分配更多内存,因此这只会导致您的代码写入实际分配的 space 末尾)。

它可能看起来像:

void grow( int newCapacity )
{
    if ( newCapacity < arrayCapacity )
        return;   // we do not need to shrink

    int *newData = new int [new_capacity];
    if ( arraySize > 0 )
        std::copy(arrayData, arrayData + arraySize, newData);
    delete[] arrayData;
    newData = arrayData;
}

然后你可以修改grow()(如果你还想保留那个),push_back()也可以调用这个函数。


注意 clear() 函数只需要做 arraySize = 0; 。它不需要释放任何内存;您可以保留该容量以备将来使用。