简体   繁体   English

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

[英]Calling delete[] breaks my C++ program

Updated: Thanks for the quick replies. 更新:感谢您的快速答复。 It seems that I have posted an older version of the code. 看来我已经发布了旧版本的代码。 Everything remains the same except for the parameterized constructor. 除了参数化的构造函数外,其他所有内容均相同。 There are a few flaws in the code as you can see, but bare in mind that I am not fully completed with this. 如您所见,代码中存在一些缺陷,但是请记住,我还没有完全完成此工作。 Currently I am more worried about the array since this is a new concept introduced yesterday. 目前,我更担心数组,因为这是昨天引入的新概念。 I have tried several different things and researched this for hours. 我尝试了几种不同的方法,并进行了数小时的研究。 Most of the responses say to just use the vector class but this is for homework which helps us understand memory allocation and dynamic arrays. 大多数响应都说只使用向量类,但这是用于家庭作业的,这有助于我们了解内存分配和动态数组。 Currently this is my .cpp and .h file that is giving me problems. 目前,这是我的.cpp和.h文件,给我带来了问题。 Every time the delete (or the clear function) operation is triggered an error occurs that states blahblah.exe has triggered a break point. 每次触发删除(或清除功能)操作时,都会发生错误,指出blahblah.exe已触发断点。

MyVector.h 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 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();
    }
}

You have a number of problems I can see already: 您有很多问题,我已经可以看到:

  1. You should not be calling the constructor explicitly like this. 您不应像这样显式调用构造函数。 It doesn't do what you think. 它没有按照您的想法做。 Put allocations in a real member function. 将分配放入真实的成员函数中。
  2. Every time you "grow" your array, you just allocate new, causing a leak because the previous pointer wasn't deleted. 每次“增长”数组时,您都只是分配新数组,这会导致泄漏,因为之前的指针没有被删除。
  3. The main issue you're asking about: You're not even storing the pointer you allocate in the constructor. 您要问的主要问题:您甚至没有将分配的指针存储在构造函数中。 Change int* theData = new int [capacityIn]; 更改int* theData = new int [capacityIn]; to theData = new int [capacityIn]; theData = new int [capacityIn]; . You're doing it correctly in your first constructor for example. 例如,您在第一个构造函数中做的正确。
  4. You are not initializing arraySize or arrayCapacity in your second constructor ( MyVector(int) ). 您还没有初始化arraySizearrayCapacity在你的第二个构造函数( MyVector(int)

Nitpicks: 刺针:

  1. You don't need to check for nullptr before deleting. 删除之前,无需检查nullptr
  2. There's no need to new int[0] . 不需要new int[0] You should never access the memory, so just initialize it to nullptr . 您永远不要访问内存,因此只需将其初始化为nullptr

Here: 这里:

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

You declare a local pointer theData that shadows the theData data member of the current object, leaving it uninitialized. 您声明一个局部指针theData ,该指针theData了当前对象的theData数据成员, theData初始化它。 From there, all bets are off on using it, and it is pure happenstance that it is the delete[] where your program finally crashes. 从那里开始,所有赌注都禁止使用它,纯属偶然,因为它是delete[]程序最终崩溃的地方。 Write

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

instead, and arraySize and arrayCapacity will have to be initialized as well. 相反,和arraySizearrayCapacity将不得不以及初始化。

Apart from that, you'll run into the problem that 除此之外,您还会遇到这样的问题

MyVector(arrayCapacity);

in the push_back function allocates a temporary object of type MyVector that is (almost) immediately destroyed again; push_back函数中分配一个MyVector类型的临时对象,该对象(几乎)立即被再次销毁; it does not change the current object. 它不会更改当前对象。

This is causing you the problem you cannot solve: 这导致您无法解决的问题:

int* theData = new int [capacityIn];

You are saying: "Please define an integer pointer..." and so on. 您在说:“请定义一个整数指针...”,依此类推。 The member variables are different than the variables you are defining inside you methods; 成员变量不同于您在方法内部定义的变量。 it makes no sense to do that. 这样做是没有意义的。 Instead, you should have done that: 相反,您应该这样做:

theData = new int [capacityIn];

or, just for educational purposes (and in order for you to understand we are assigning to a member variable): 或者,仅出于教育目的(为了使您理解,我们将其分配给成员变量):

this->theData = new int [capacityIn];

Also (some points may not be that important, but I would like to point them out since you are a new guy): 另外(某些观点可能并不那么重要,但由于您是新手,所以我想指出这些观点):

  1. Please set your other variables in the second constructor, it seems you have forgotten to do so. 请在第二个构造函数中设置其他变量,看来您已经忘记这样做了。

     MyVector::MyVector(int capacityIn) { theData = new int [capacityIn]; arraySize = capacityIn; arrayCapacity = capacityIn; } 
  2. You should have meaningful names, theData is something you should definitely avoid. 您应该使用有意义的名称,您绝对应该避免使用theData http://petdance.com/2012/04/the-worlds-two-worst-variable-names/ http://petdance.com/2012/04/the-worlds-two-worst-variable-names/

  3. Your methods should start with a verb, eg getDimension() getCapacity() and so on. 您的方法应以动词开头,例如getDimension() getCapacity()等。
  4. Constructors are... constructors , which means they are meant to be called whenever an item is constructed or created . 构造函数是... 构造函数 ,这意味着在构造创建项目时都将调用它们。 You definitely should not explicitely call a constructor in any way. 您绝对不应该以任何方式显式调用构造函数。
  5. This is a basic rule: whenever you access the memory with the new command, you should call delete somewhere after some time. 这是一条基本规则:每当您使用new命令访问内存时,都应在一段时间后调用delete Your code has severe memory leaks. 您的代码存在严重的内存泄漏。

I might have been able to help you more, but I do not exactly understand what you are trying to accomplish in some methods, namely in grow() and pushBack() . 我也许可以为您提供更多帮助,但是我无法完全理解您要通过某些方法(即grow()pushBack()

It's not good style to initialize variables via assignment statements inside the constructor body. 通过构造函数体内的赋值语句初始化变量的样式不好。 Instead, variables should be initialized before the constructor body is entered. 相反,应在输入构造函数主体之前初始化变量。

You can either do this by using the member initializer list , or by supplying default values in the class definition. 您可以通过使用成员初始化器列表或在类定义中提供默认值来执行此操作。 The latter seems easiest here: 后者似乎在这里最简单:

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

In the constructor then instead of duplicating code you should leverage existing functions to do the same thing: 然后在构造函数中,而不是复制代码,您应该利用现有函数来执行相同的操作:

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

Currently you don't actually have a function to increase the capacity so you will need to add one. 当前,您实际上没有增加容量的功能,因此您需要添加一个。 (The grow() function makes the int variable increase but you don't allocate any more memory so this just results in your code writing past the end of the space that is actually allocated). grow()函数使int变量增加,但是您不分配更多的内存,因此这只会导致您的代码写在实际分配的空间的末尾)。

It might look like: 它可能看起来像:

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;
}

Then you can modify grow() (if you still want to keep that), and push_back() to also call this function. 然后,您可以修改grow() (如果您仍然想要保留它)和push_back()以也调用此函数。


Note that the clear() function simply needs to do arraySize = 0; 注意, clear()函数只需要执行arraySize = 0; . It doesn't need to free any memory; 它不需要释放任何内存。 you can leave that capacity available for future use. 您可以将该容量留作将来使用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM