调用delete[]会中断我的C++程序

Calling delete[] breaks my C++ program

本文关键字:我的 C++ 程序 中断 delete 调用      更新时间:2023-10-16

更新:感谢您的快速回复。我似乎发布了一个旧版本的代码。除了参数化构造函数之外,所有内容都保持不变。正如你所看到的,代码中有一些缺陷,但请记住,我还没有完全完成这项工作。目前我更担心数组,因为这是昨天引入的一个新概念。我尝试了几种不同的方法,并对此进行了数小时的研究。大多数回复都说只使用向量类,但这是家庭作业,有助于我们理解内存分配和动态数组。目前,这是我的.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();
    }
}

我已经看到了很多问题:

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

Nitticks:

  1. 删除之前不需要检查nullptr
  2. 不需要new int[0]。您永远不应该访问内存,所以只需将其初始化为nullptr即可

此处:

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

您声明了一个本地指针theData,该指针遮蔽当前对象的theData数据成员,使其未初始化。从那时起,所有的赌注都押在了使用它上,而你的程序最终崩溃的地方正是delete[],这纯属偶然。写入

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

arraySizearrayCapacity也必须被初始化。

除此之外,你还会遇到

MyVector(arrayCapacity);

在CCD_ 14函数中分配类型为CCD_;它不会改变当前对象。

这会给您带来无法解决的问题:

int* theData = new int [capacityIn];

你说:"请定义一个整数指针…"等等。成员变量与你在方法中定义的变量不同;那样做毫无意义。相反,你应该这样做:

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()

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

可以使用成员初始值设定项列表,也可以在类定义中提供默认值。后者在这里似乎最简单:

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变量增加,但不分配更多内存,因此这只会导致代码写入超过实际分配的空间的末尾)。

它可能看起来像:

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;即可。它不需要释放任何内存;您可以保留该容量以备将来使用。