为什么在调用std :: map :: clear()之后仍然可以访问内存?

sne*_*neg 18 c++ stdmap

我正在观察std :: map :: clear()的奇怪行为.这个方法应该在调用时调用元素的析构函数,但是在调用clear()之后仍然可以访问内存.

例如:

struct A
{
  ~A() { x = 0; }
  int x;
};

int main( void )
{
  std::map< int, A * > my_map;
  A *a = new A();
  a->x = 5;
  my_map.insert( std::make_pair< int, *A >( 0, a ) );

  // addresses will be the same, will print 5
  std::cout << a << " " << my_map[0] << " " << my_map[0]->x << std::endl;

  my_map.clear();

  // will be 0
  std::cout << a->x << std::endl;

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

问题是,为什么变量a在map :: clear()调用析构函数后仍然可以访问?我需要delete a;在打电话后写字my_map.clear()还是可以安全地覆盖内容a

在此先感谢您的帮助,谢谢

小智 22

如果您将指针存储在地图(或列表或类似内容)上,则负责删除指针,因为地图不知道它们是否已使用new创建.如果不使用指针,clear函数仅调用析构函数.

哦,还有一件事:调用析构函数(甚至调用delete)并不意味着无法再访问内存.这只意味着如果你这样做,你将访问垃圾.

  • 只有你自己可以访问垃圾,但有时你会访问一个尚未变成垃圾的区域,所以它似乎有效了一段时间.这就是为什么"但它有效,所以我可以逃脱它"是完全错误的. (6认同)

小智 20

std :: map不管理指针值指向的内存 - 这取决于你自己做.如果您不想使用智能指针,可以编写一个通用的免费和清除函数,如下所示:

template <typename M> void FreeClear( M & amap ) 
    for ( typename M::iterator it = amap.begin(); it != amap.end(); ++it ) {
        delete it->second;
    }
    amap.clear();
}
Run Code Online (Sandbox Code Playgroud)

并使用它:

std::map< int, A * > my_map;
// populate
FreeClear( my_map )
Run Code Online (Sandbox Code Playgroud)

;