【发布时间】:2022-06-10 21:06:55
【问题描述】:
我尝试使用模板类制作我的自定义 Vector 类。
我希望我可以将我的 Vector<int> 放入 Vector<Vector<int>> 变量中。至少这是我所希望的……但它总是在析构函数代码处崩溃。
这是我的代码。
#include <iostream>
#include <string>
template <typename T>
class Vector {
T* data;
int capacity;
int length;
public:
typedef T value_type;
Vector() {}
Vector(int n) : data(new T[n]), capacity(n), length(0) {}
void push_back(T input) {
data[length++] = input;
}
T operator[](int i) { return data[i]; }
virtual ~Vector() { if (data) delete[] data; }
};
int main() {
Vector<Vector<int>> v(3);
Vector<int> vv(4);
v.push_back(vv);
}
所以我想,也许我应该使用复制构造函数,因为似乎问题是v 在vv 之前被删除。好吧,如果我只是注释掉析构函数代码,它会起作用,但我觉得这不太合适......
所以我做了一个这样的自定义复制构造函数:
Vector(const T& other) {
}
但它给了我一个错误,说“模棱两可的重载”......回头看,当然是错误的,因为data的T与other的T不同......
如何使我的自定义 Vector 类正常工作? (即我希望 push_back 按我的意图工作......)
【问题讨论】:
-
const T& other->const Vector<T>& other? -
除非你初始化
data,否则这个成员变量的值可以是任意的。除非此值恰好为 null,否则调用delete[]会导致未定义的行为,在这种情况下会使您的程序崩溃。 (您的默认构造函数不会将其初始化为 null。)顺便说一句:delete[]可以使用 null 作为操作数来调用;在这种情况下,它根本什么都不做。在析构函数中检查data是否为 null 是不必要的。 -
注意:如果你想让
v[0].push_back(1);为Vector<Vector<int>>工作,你应该引用[]运算符:T& operator[](int i) { ... }此外,我建议对索引使用无符号整数类型。通常size_t用于此目的,这也是capacity/length的首选类型。 -
正确实现向量并非易事,因为它必须涉及放置
new。 -
您的类构造函数显式地进行动态内存分配。您需要确保所有构造函数(包括复制/移动构造函数)在需要时分配内存,并且赋值(复制/移动)运算符在需要时正确重新分配内存,否则复制
Vector的实例将导致析构函数释放一些内存两次 - 这会导致未定义的行为。这些函数的隐式生成的默认值不会这样做。有关更多信息,请查看“三规则”或(C++11 及更高版本)“五规则”。
标签: c++ vector containers destructor rule-of-five