c++ - 我的自定义向量有一个运行时错误调试断言失败:_CrtIsValidHeapPointer(block)
问题描述
我的向量类的一部分
class CVector
{
friend ostream &operator<<(ostream& output, const CVector& vec);
public:
CVector()
{
sPtr = new char[10];
size = 0;
capacity = 10;
}
CVector(const CVector &vec)
{
size = vec.size;
capacity = vec.capacity;
sPtr = new char[size];
cout << "copy constructor" << endl;
for (size_t i = 0; i < size; i++)
{
sPtr[i] = vec.sPtr[i];
}
}
主功能
CVector veca;
cout << veca.getCapacity() << endl;
cout << veca.getSize() << endl;
veca.push_back('H');
veca.push_back('e');
veca.push_back('l');
veca.push_back('l');
veca.push_back('o');
cout << "Add five elements:Hello" << endl << "result:" << veca << " size:" << veca.getSize() << " capacity:" << veca.getCapacity()<<endl;
CVector vecb,vecc;
vecb.push_back('H');
vecb.push_back('i');
vecc = vecb;
在这段代码(vecc = vecb)之后,问题发生了。我认为复制构造器出了点问题,但我不知道出了什么问题
push_back 函数
void push_back(char c)
{
if (size == capacity-1)
{
char* temp = new char[2 * capacity];
for (size_t i = 0; i < capacity; i++)
{
temp[i] = sPtr[i];
}
delete[] sPtr;
capacity *= 2;
sPtr = temp;
}
sPtr[size] = c;
size++;
}
我可以将 *temp 本地指针分配给 *sPtr(指向我的向量的数组的指针)吗
解决方案
在您的复制构造函数中,您分配vec.size
字节,但设置capacity
为vec.capacity
. 您可能想要分配vec.capacity
字节。
接下来是,复制构造和复制分配之间存在差异:
CVector vecb(veca); // this calls the copy constructor
CVector vecc; // this calls the default constructor
vecc = vecb; // this calls the copy assignment operator
由于您没有给出复制赋值运算符的实现,编译器将为您生成一个,看起来像这样:
CVector & operator = (const CVector & other) {
size = other.size;
capacity = other.capacity;
sPtr = other.sPtr;
}
这不适合你,因为
- 你失去了sPtr的踪迹,没有人
delete
知道它。 - 现在两个不同
CVector
的 s 通过 指向同一个内存sPtr
。当CVector
调用 first 的析构函数时,它将delete sPtr
. 然后另一个CVector
将指向已经是delete
d 的内存。当它的析构函数(或任何其他成员函数)被调用时,它会尝试delete
访问或访问该delete
d 内存。
这就是规则 3(或规则 5,取决于您是否实现移动语义)的原因。
实现复制(和移动)赋值运算符的一种简单而好的方法是使用复制和交换习语:
void swap(CVector & other) {
std::swap(size, other.size);
std::swap(capacity, other.capacity);
std::swap(sPtr, other.sPtr);
}
CVector & operator = (const CVector& other) {
CVector tmp(other); // make a copy of other
this->swap(other); // by swapping with other, tmp's destructor, will cleanup your previous sPtr
return *this;
}
推荐阅读
- java - java.io.IOException:使用 JVM v1.8.0_162 启动 Tomcat v9.0.2.0 时无法建立环回连接
- python - 计算许多分布的 KL 散度
- javascript - 同一台机器上的两个节点脚本可以互相阻塞吗?
- tfs - VSTS - 访问自定义过程
- javascript - 如何防止 JavaScript 数组填充页面加载?
- javascript - 样式化openstreetmap 道路、缩放等
- c# - 将值传递给泛型类型
- declaration - Ionic 4 中 2 个模块的声明
- sql - SQL 查询:返回带空格的名字和姓氏的更好选择?
- ios - iOS 11 | CSS:背景渲染问题