【问题标题】:Error while trying to declare a push back method in a vector class that i created尝试在我创建的向量类中声明推回方法时出错
【发布时间】:2021-12-27 11:21:29
【问题描述】:

我创建了一个通过创建动态数组来模拟 C++ 向量动作的类,我尝试为该类创建一个推回方法,该方法首先检查数组是否已填充,如果是,它将: 1- 将当前数组的内容复制到双倍大小的临时数组 2-删除旧的动态数组 3-使用旧数组的双倍大小创建一个新的动态数组(临时数组的大小相同) 4- 将临时数组的内容复制到新的动态数组中

错误是当我使用以下代码时,我只能将数组的大小加倍一次,然后它会抛出错误: HEAP [ConsoleApplication1.exe]:指定给 RtlValidateHeap 的地址无效(016C0000、016CDB98) ConsoleApplication1.exe 已触发断点。

#include <iostream>

using namespace std;

class SimpleVector {
private:
    int* item; //pointer to the dynamic array (the vector)
    int size;
    int numElements;

public:
    SimpleVector(int size) {
        this->size = size;
        this->numElements = 0;
        this->item = new int[this->size];
    }
    SimpleVector():SimpleVector(10){}

    void pushBack(int element) {
        //check for overflow
        if (numElements >= size) {
            int newSize = size * 2;
            
            int* temp = new int[newSize]; // temporary array with the double size to hold old array elements
            for (int i = 0; i < numElements; i++) {
                temp[i] = item[i];
            }
            delete[] item;
            size = newSize;


            //****ERROR IS IN THIS PART****
            int* item = new int[size]; 
            for (int i = 0; i < numElements; i++) {
                item[i] = temp[i];
            }
            //****END OF THE PART CONTAINING ERROR****


            item[numElements++] = element;
            cout << "Added: " << element << endl;
            cout << "Size is: " << size << endl;
        }
        else {
        item[numElements++] = element;
        cout << "Added: " << element << endl;
        cout << "Size is: " << size << endl;
    }
    }
};

int main() {
    
    SimpleVector v1(2);
    v1.pushBack(1);
    v1.pushBack(2);
    v1.pushBack(3);
    v1.pushBack(4);
    v1.pushBack(5);
    v1.pushBack(6);
    v1.pushBack(7);
    

    return 0;
}

此程序推送前 4 个项目,然后在尝试将尺寸加倍为 8 时引发错误

当我将包含错误的部分替换为:

item = temp

它工作正常,但我不明白为什么会发生这种情况。

【问题讨论】:

    标签: c++ arrays class oop vector


    【解决方案1】:

    您的代码有几个问题。我建议您阅读有关如何正确遵守 Rule of Three/Five/Zero 的信息,我不打算在这里介绍。我只是想这是出于某种邪恶的学术目的,所以我会尽量简短,但阅读链接的文章。

    也就是说,这个:

    int *item = new int[size];
    for (int i = 0; i < numElements; i++)
    {
        item[i] = temp[i];
    }
    

    毫无意义。这会引发一连串的不良行为,这些行为只会随着它的发展而变得更糟。

    • 您已经有一个成员变量item。此代码声明了一个名为item本地 变量,其名称​​隐藏 成员item。因此,new 运算符的初始化值存储在本地,而不是成员中。
    • 现在由本地 var item(不是成员)指向的内存在函数退出时丢失,因为只有本地 item 指向它。
    • 开始时,额外的分配毫无意义。您已经创建了一个由temp 指向的新向量副本,并且已经将所有合法项目从memver-var item 内存复制到temp 内存。编写的代码也泄漏了temp 分配。
    • 您销毁了 member-var item 内存,使指针现在悬空,此后通过取消引用或 eval 进行的任何使用都会调用未定义的行为。

    因此,总而言之,您制作了一个有价值的扩展副本,泄漏它,制作一个毫无价值的副本,也泄漏 it,最后留下一个不再指向任何已定义内容的成员变量.

    整个函数可能看起来更像这样:

    void pushBack(int element)
    {
        // check for overflow
        if (numElements >= size)
        {
            int newSize = size * 2;
    
            int *temp = new int[newSize];
            for (int i = 0; i < numElements; i++)
            {
                temp[i] = item[i];
            }
            delete[] item;
            size = newSize;
            item = temp;
        }
        item[numElements++] = element;
        cout << "Added: " << element << endl;
        cout << "Size is: " << size << endl;
    }
    
    

    【讨论】:

    • 好建议,好改进。但是,原始代码中仍然存在一个错误,即如果“向量”的大小为 0,则将其加倍不会为新元素腾出空间。
    • 很清楚这一点。我想我已经重写了足够多的 OP 代码。就个人而言,我首先不理解构造分配的愿望。 AFAIC 初始床应为空,尺寸应为零,扩展测试应为numElements == size,扩展尺寸应为int newSize = size ? 2 * size : 1;。我还编写了正确的复制 ctor、移动 ctor,以及复制分配和移动分配运算符。但是除了用勺子喂食之外,OP 迟早要学会一些。
    猜你喜欢
    • 1970-01-01
    • 2017-09-17
    • 2016-02-04
    • 1970-01-01
    • 1970-01-01
    • 2021-08-05
    • 2018-08-03
    • 2014-07-20
    • 2022-12-09
    相关资源
    最近更新 更多