Как мне поступить с деструктором при создании пользовательского вектора с помощью класса шаблона?
Я попытался создать свой собственный класс 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
...
Как я могу сделать свой заказVector
классная работа? (т.е. я хочу, чтобы push_back работал так, как я предполагал...)
1 ответ
Общий вопрос
При проектировании классов, особенно когда речь идет о распределении памяти/ресурсов, обычно необходимо следовать «правилу пяти» (которое до C++11 было «правилом трех»):
Если вы реализуете любой из:
- Деструктор
- Оператор присваивания копирования/перемещения
- Конструктор копирования/перемещения
тогда вам, вероятно, потребуется реализовать их все.
Причина в том, что каждый из них, вероятно, должен иметь некоторую логику управления ресурсами, помимо того, что язык дает вам по умолчанию.
Сигнатуры этих пяти методов для вашего класса будут такими:
Ваш конкретный класс
В вашем конкретном случае есть несколько конкретных проблем:
- Как предполагает @UnholySheep, вы неправильно объявили конструктор копирования.
- Вы реализовали конструктор по умолчанию; но - он ничего не выделяет и ничего не инициализирует!
data
указатель содержит произвольный мусор, и когда вы пытаетесь его освободить, скорее всего, произойдут плохие вещи. - Вы довольно много копируете
T
значения, которые для внешнего вектора были быVector<int>
значения - и это может дорого обойтись. - Даже если вы исправили вышеперечисленное, вы все равно должны реализовать недостающие методы из «правила пяти».