我正在开发一个Matrix类,它使用矢量矢量实现:
class Matrix {
private:
int r, c;
std::vector<std::vector<double> > grid;
public:
//things
目前我正在实现析构函数,并考虑过它。在我(聪明地)切换到std::vector
之前我使用了double ** grid
。这意味着有一些new
调用,因为每个指针都指向一个数组(这也是我相信的指针......或者我遇到的错误无论如何......)。无论如何,析构函数看起来像:
Matrix::~Matrix() {
for (int i = 0; i < r; i++) {
delete [] grid[i]
delete [] grid
现在我试图复制它(可能是不必要的?)并且具有以下内容:
Matrix::~Matrix() {
std::vector<std::vector<double> >::iterator it = this->grid.begin();
for (it; it != this->grid.end(); it++) {
(*it).clear()
this->grid.clear();
std::vector<std::vector<double> >().swap(this->grid);
和
Matrix::~Matrix() {
this->grid.clear();
std::vector<std::vector<double> >().swap(this->grid);
我倾向于选择后者,因为clear()
应该完全破坏内部向量(不仅仅是内部向量的内容),然后复制和交换习惯用法临时矢量的效果是解除原始外部矢量的记忆。前者让我认为我clear()
每个内部向量的内容,但是留下了n个空的,仍在内存中的向量,并且必须在每个向量上调用临时交换机制(因此可能[未经测试]影响我的迭代器)。
在外部向量上调用clear()
是否通过调用它们的析构函数完全释放用于内部向量的内存?我不确定他们的析构函数是否以交换习惯用法的方式解除分配。
答案 0 :(得分:4)
注意,这个析构函数比你想象的要复杂。我们走了:
好的,实际上,事实并非如此。您可以感谢rule of zero这个灵活的实现。由于std::vector
是一个行为良好的类(模板),可以通过RAII正确管理其资源,因此您的类的默认生成的析构函数可以在不输入任何内容的情况下执行正确的操作。
如果出于任何原因,您仍需要该析构函数的显式签名,则可以在类中使用以下语法:
~Matrix() = default;
或者,如果您需要将定义设置为不在线,请正常声明析构函数,但这样定义它:
Matrix::~Matrix() = default;
答案 1 :(得分:0)
您不需要编写显式析构函数。当您超出此2D矢量定义的范围时,默认析构函数序列将处理销毁部分。 2D向量的每个元素都是1D向量,1D向量的每个元素都是double
,因此默认的破坏序列将首先破坏grid [0],如下图所示,这反过来又会破坏每个double
存储在grid [0]中的元素,之后它将对grid [1]重复相同的操作,依此类推。
_____
_____ grid[0] of doubles |_|_|_|....
|_____ grid[1] of double
grid--> |_____ grid[2] of double
|_____ grid[3] of double
|_____ grid[4] of double