首页 > 解决方案 > c ++:清除向量的向量似乎将向量元素留在原处

问题描述

这被标记为重复,因为它声称它已经在这里得到了回答。我觉得我的问题根本没有得到回答,因为那篇文章根本不涉及向量或类似的容器。对我的问题的评论也没有回答。因此,基于我将问题埋得太深的理论,我会在我的例子之前把它放在前面。

当我们在向量上调用 .clear() 时,它会在向量的每个元素上调用析构函数。“众所周知”的例外是当它是指针向量时。我下面的示例表明,当我们 .clear() 一个向量向量时,析构函数显然不会在作为其元素的向量上被调用,因为之后我仍然可以访问它们。为什么?向量以什么方式“有点像”指针,以便不会调用析构函数?

要清楚一些事情:

它出现是因为在一个很长的程序中出现了意外行为,我将问题追溯到这个。我修复了它,但仍然对为什么该程序巧妙地失败而不是壮观地失败感到困惑。

好的,这是原始问题:


这里还有一些与此相关的其他问题,例如这个这个,但我认为它们并不能完全解决我想知道的问题。我的理解是,在向量上调用 clear 会在向量的每个元素上调用析构函数(但请参阅下面的例外情况)。因此,对于向量的向量,我会假设析构函数将在向量向量中的每个向量上调用。这似乎是不正确的。我知道几种编写代码来处理它的方法。但是我仍然对这种行为感到有些困惑。此代码显示了行为:

using namespace std;

#include <iostream>
#include <vector>


void writeMat(vector<vector<double>> &vec);

int main()
{
  vector<vector<double>> b;

  writeMat(b);

  // Trying to get b[0].size() here results in a core dump, as expected.

  vector<double> btry1 = {1.0, 2.0};
  vector<double> btry2 = {3.0, 4.0};

  b.push_back(btry1);
  b.push_back(btry2);

  cout << "Added some stuff to the vector." << endl;
  writeMat(b);

  b.clear();
  cout << "Cleared the vector.  Now it is: " << endl;
  writeMat(b);

  cout << "But final check...  b.size() = " << b.size() << " and b[0].size() = " << b[0].size() << endl;

  return 0;
}


void writeMat(vector<vector<double>> &vec)
{
  cout << "vec.size() = " << vec.size() << endl;
  for (int i = 0; i < vec.size(); i++)
    {
      cout << "vec[" << i << "].size() = " << (vec[0]).size() << endl;
    }

  cout << "vec is: " << endl << "--------------------" << endl;
  for (int i = 0; i < vec.size(); i++)
    {
      for (int j = 0; j < vec[i].size(); j++)
    {
      cout << vec[i][j] << "  ";
    }
      cout << endl;
    }
  cout << "--------------------" << endl;
}

生成输出:

vec.size() = 0
vec is: 
--------------------
--------------------
Added some stuff to the vector.
vec.size() = 2
vec[0].size() = 2
vec[1].size() = 2
vec is: 
--------------------
1  2  
3  4  
--------------------
Cleared the vector.  Now it is: 
vec.size() = 0
vec is: 
--------------------
--------------------
But final check...  b.size() = 0 and b[0].size() = 2

我希望在调用b[0].size()之后调用b.clear()会导致核心转储,就像我在将任何元素添加到 b 之前调用它一样。但相反,它返回值 2,这表明虽然b.size()现在为零,但b[0]仍然在内存中徘徊。确实,修改上面的代码我发现,之后b.clear(),还是会报,比如,b[0][1]就是2。

在这里看到,对于像这样的向量vector<MyClass>,在调用时会在向量的每个元素上调用析构函数,clear()但对于像这样的指针向量vector<MyClass*>则不会。所以我猜一个向量在某种程度上与一个指针“更相似”,而不是一个对象。对我来说,像向量这样的容器与更原始的类型有什么关系,我从来都不是很清楚。我认为向量是一个旧式数组(不是 std::array,一个像我们在 20 年前在 C 中使用的旧数组......)具有相当薄的方法包装以使其更友好。但这并不完全正确,因为将指针传递给向量与将指针传递给数组具有非常不同的效果。

所以,我想我的问题大致是这样的:向量不是指针。但是当清除向量向量时,行为似乎类似于清除指针向量。那么导致这种行为的相似性是什么?我意识到这很可能会深入了解为向量预留的内存块的外观,而不是为数组预留的内存块的外观。

我突然想到这可能特定于 C++ 的实现。我在 Linux 操作系统中使用 g++。

标签: c++vectordestructor

解决方案


推荐阅读