我遇到了一些错误,后退功能出现内存错误,并且无法通过程序检查的许多测试。
我需要使此代码正常工作,该代码位于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_();
}
答案 0 :(得分: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;
}
答案 1 :(得分:0)
push_back()
和insert()
都调用grow()
,由于capacity
是GROWER
,因此{{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 。
0
和size_t
在迭代数组时超出范围。
size_t
和erase()
不应为空数组返回operator==
。并且begin()
将返回一个指向非空数组中最后一个元素的指针,而不是返回指向最后一个元素之后的1的指针。
end()
和nullptr
在迭代数组之前,不执行任何边界检查以确保2个向量具有相同的end()
。他们正在比较operator==
之后的元素值。另外,operator!=
返回错误的结果。
话虽如此,请尝试以下类似操作:
n_elems