在项目的向量类中创建动态数组时出错

时间:2020-11-12 22:10:22

标签: c++ arrays vector

我遇到了一些错误,后退功能出现内存错误,并且无法通过程序检查的许多测试。

我需要使此代码正常工作,该代码位于Vector.cpp中:

#include <stdexcept>
#include "Vector.h"

using namespace std;

void Vector::grow()
{
    const int GROWER = 1.6;
    capacity = capacity * GROWER;
}

Vector::Vector()
{
    capacity = CHUNK;
    n_elems = 0;
    data_ptr = new int[capacity];
    for (size_t i = 0; i < capacity; i++)
    {
        data_ptr[i] = 0;
    }
}

Vector::Vector(const Vector& v)
{
    n_elems = 0;
    capacity = v.capacity;
    data_ptr = new int[capacity];
    for (size_t i = 0; i < capacity; i++)
    {
        data_ptr[i] = v.data_ptr[i];
        n_elems++;
    }
}

Vector& Vector::operator=(const Vector& v)
{
    capacity = v.capacity;
    data_ptr = new int[capacity];
    for (size_t i = 0; i < capacity; i++)
    {
        data_ptr[i] = v.data_ptr[i];
    }
    return *this;
}

Vector::~Vector()
{
    delete[] data_ptr;
}

int Vector::front() const
{
    if (n_elems != 0)
    {
        return data_ptr[0];
    }
    else
    {
        return -1;
        throw range_error("Range Error");
    }
}

int Vector::back() const
{
    if (n_elems != 0)
    {
        return data_ptr[n_elems - 1];
    }
    else
    {
        throw range_error("Range Error");
    }
}

int Vector::at(size_t pos) const
{
    if (pos >= 0 && pos < capacity)
    {
        return data_ptr[pos];
    }
    else
    {
        throw range_error("Range Error");
    }
}

size_t Vector::size() const
{
    return n_elems;
}

bool Vector::empty() const
{
    if (n_elems == 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

int& Vector::operator[](size_t pos)
{
    return data_ptr[pos];
}

void Vector::push_back(int item)
{
    grow();
    data_ptr[n_elems - 1] = item;
}

void Vector::pop_back()
{
    if (n_elems >= 0)
    {
        --n_elems;
    }
    else
    {
        throw range_error("Range Error");
    }
}

void Vector::erase(size_t pos)
{
    if (pos >= 0 && pos < capacity)
    {
        for (size_t i = pos; i < capacity; i++)
        {
            data_ptr[i] = data_ptr[i + 1];
        }
        n_elems--;
    }
    else
    {
        throw range_error("Range Error");
    }
}

void Vector::insert(size_t pos, int item)
{
    int moveCount = n_elems - pos;
    grow();
    if (pos >= 0 && pos < capacity)
    {
        for (size_t i = n_elems; i >= 0; i--)
        {
            data_ptr[i] = data_ptr[i - 1];
        }
        data_ptr[pos] = item;
        n_elems++;
    }
    else
    {
        throw range_error("Range Error");
    }
}

void Vector::clear()
{
    n_elems = 0;
}

int* Vector::begin()
{
    if (n_elems == 0)
    {
        return nullptr;
    }
    else
    {
        return data_ptr;
    }
}

int* Vector::end()
{
    if (n_elems == 0)
    {
        return nullptr;
    }
    else
    {
        return (data_ptr + (n_elems - 1));
    }
}

bool Vector::operator==(const Vector& v) const
{
    bool flag = true;
    for (size_t i = 0; i < capacity; i++)
    {
        if (data_ptr[i] == v.data_ptr[i])
        {
            flag = true;
        }
        else
        {
            flag = false;
            break;
        }
    }
    return flag;
}

bool Vector::operator!=(const Vector& v) const
{
    bool flag = true;
    for (size_t i = 0; i < capacity; i++)
    {
        if (data_ptr[i] != v.data_ptr[i])
        {
            flag = true;
        }
        else
        {
            flag = false;
            break;
        }
    }
    return flag;
}

要通过这些测试,这些测试位于名为testVector.cpp的文件中:

#include "Vector.h"
#include "test.h"
#include <stdexcept>
using namespace std;

int main() {
    // Test exceptions
    Vector v;
    throw_(v.at(0), range_error);
    throw_(v.pop_back(), range_error);
    throw_(v.erase(0), range_error);
    throw_(v.front(), range_error);
    throw_(v.back(), range_error);

    // Test adding an element
    v.push_back(1);
    test_(v.size() == 1);
    test_(v.at(0) == 1);
    test_(v[0] == 1);
    test_(v.front() == 1);
    test_(v.back() == 1);
    test_(!v.empty());

    // Add another
    v.push_back(2);
    test_(v.size() == 2);
    test_(v.at(0) == 1);
    test_(v.at(1) == 2);
    test_(v[0] == 1);
    test_(v[1] == 2);
    test_(v.front() == 1);
    test_(v.back() == 2);
    test_(!v.empty());

    // Test iterators
    auto iter = v.begin();
    test_(*iter == 1);
    ++iter;
    test_(*iter == 2);
    ++iter;
    test_(iter == v.end());

    // Test copy and ==
    Vector v2 = v;
    test_(v2.size() == 2);
    test_(v2.at(0) == 1);
    test_(v2.at(1) == 2);
    test_(v2[0] == 1);
    test_(v2[1] == 2);
    test_(v2.front() == 1);
    test_(v2.back() == 2);
    test_(!v2.empty());
    test_(v == v2);

    iter = v2.begin();
    test_(*iter == 1);
    ++iter;
    test_(*iter == 2);
    ++iter;
    test_(iter == v2.end());

    // Test assignment
    Vector v3;
    v3 = v;
    test_(v3.size() == 2);
    test_(v3.at(0) == 1);
    test_(v3.at(1) == 2);
    test_(v3[0] == 1);
    test_(v3[1] == 2);
    test_(v3.front() == 1);
    test_(v3.back() == 2);
    test_(!v3.empty());

    //iter = v3.begin();
    //test_(*iter == 1);
    //++iter;
    //test_(*iter == 2);
    //++iter;
    //test_(iter == v3.end());

    // Test assignment
    v[1] = -2;
    test_(v.back() == -2);
    test_(v.at(1) == -2);
    test_(v[1] == -2);

    // Test pop_back
    v.pop_back();
    test_(v.size() == 1);
    test_(v.front() == 1);
    test_(v.back() == 1);
    test_(v.at(0) == 1);
    test_(v[0] == 1);

    // Test clear and !=
    v.clear();
    test_(v.size() == 0);
    test_(v.empty());
    throw_(v.at(0), range_error);
    throw_(v.pop_back(), range_error);
    throw_(v.erase(0), range_error);
    throw_(v.front(), range_error);
    throw_(v.back(), range_error);
    test_(v != v2);

    // Test erase
    v3.erase(0);
    test_(v3.size() == 1);
    test_(v3.at(0) == 2);
    test_(v3[0] == 2);
    test_(v3.front() == 2);
    test_(v3.back() == 2);

    // Test insert
    //v3.insert(0,1);
    test_(v3.size() == 2);
    test_(v3.at(0) == 1);
    test_(v3[0] == 1);
    test_(v3[1] == 2);
    test_(v3.front() == 1);
    test_(v3.back() == 2);

    // Test grow
    Vector v4;
    for (int i = 1; i <= 10; ++i)
        v4.push_back(i);
    test_(v4.size() == 10);
    test_(v4.front() == 1);
    test_(v4.back() == 10);
    v4.insert(10,11);
    test_(v4.size() == 11);
    test_(v4.front() == 1);
    test_(v4.back() == 11);


    report_();
}

2 个答案:

答案 0 :(得分:0)

push_back()insert()都调用grow(),由于capacityGROWER,因此{{1} }}截断为int,乘以1.6不会改变其值。但是,即使适当地增加了1,也根本不会重新分配capacity * 1数组以适应新的capacity

但是,即使data_ptr工作正常,也不必在每次插入新元素时都调用capacity,这违背了将grow()与{{1}分开的目的。 }开始。仅当grow()达到n_elems时,才应增长数组。

您的课程还有很多其他问题:

  • capacity未测试自我分配,并且正在泄漏旧数组的已分配内存。考虑改用copy-swap idiom

  • 数组为空时,
  • n_elems不会到达capacity语句。

  • operator=front()使用throw而非at()执行边界检查。

  • erase()正在将新值插入错误的索引,而不是递增capacity

  • n_elems在数组为空时不会发生push_back()错误,导致n_elems递减到pop_back()以下,该值回绕为throw是因为n_elems unsigned

  • 0size_t在迭代数组时超出范围。

  • size_terase()不应为空数组返回operator==。并且begin()将返回一个指向非空数组中最后一个元素的指针,而不是返回指向最后一个元素之后的1的指针。

  • end()nullptr在迭代数组之前,不执行任何边界检查以确保2个向量具有相同的end()。他们正在比较operator==之后的元素值。另外,operator!=返回错误的结果。

话虽如此,请尝试以下类似操作:

n_elems

答案 1 :(得分:0)

您在这里缺少vector的声明,但是我可以推测其结构。您在这里做的第一个错误:

const int GROWER = 1.6;  
capacity = capacity * GROWER; // it will never change

重新分配不会发生,它在哪里?您只需调用不确定行为的饮食即可。

您必须使GROWER float或将大小增加固定大小。向量在几何上增长也是非常不寻常的。并且在每个push_back上增长都非常无效。相反,您必须具有一个容量和分配的大小。如果push_back会增加容量(超出其限制),则后者可能会更大并且会增加。您显然在那里有许多元素n_elems,但是您忽略了它吗?

其中许多人做了太多额外的工作,没有做应做的事情。 这样实际上可能是

data_ptr = new int[capacity] {}; // value initialization
//for (size_t i = 0; i < capacity; i++)
//{
//    data_ptr[i] = 0;
//}

使用初始化列表,而不是副作用。否则您可能会丢失它们。复制构造函数也不考虑v的n_elems,并且可能复制垃圾,将其转换为新元素。

比较简直是错误的,因为向量可以具有不同的容量。例如

bool Vector::operator==(const Vector& v) const
{
    // check here if either of vectors is empty, 
    // if both are empty, they are equal?
    // if their capacities are unequal, vectors are not equal. Those are shortcuts

    // capacities are same
    for (size_t i = 0; i < capacity; i++ )
        if (data_ptr[i] != v.data_ptr[i])
           return false;

    return true;
}
豫ICP备18024241号-1