博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

为什么不要在STL容器中存储 auto_ptr 对象

Posted on 2009-04-27 20:37  月光林地  阅读(1605)  评论(1编辑  收藏  举报

      大多数C++ 程序员都知道不要把auto_ptr 对象作为STL容器元素来使用。但是很少有人知道到底是为什么。C++标准如是说:“STL元素必须具备拷贝构造和可赋值……”,其意思是说对象可以进行安全的赋值操作,可以将一个对象拷贝到另一个对象,从而获得两个独立的,逻辑上相同的拷贝。尤其是当一个对象被拷贝到目标对象后,原来的对象不会改变。但 auto_ptr 却不然,用 auto_ptr 进行赋值和拷贝操作不仅会改变目标拷贝,而且还明显地改变原来的对象。明确地说,就是原来对象将指针的物主身份转换成目标对象,与此同时,原来对象中的指针变成了NULL。想一下下面这段代码会发生什么:

  

class Foo{};
  vector  
< auto_ptr <Foo> > vf; // 声明 auto_ptr类型向量元素
  
// 填写 vf
  int g()
  {
    auto_ptr 
<Foo> temp = vf[0]; // vf[0] 变成 null
  }

      当temp 被初始化,成员vf[0]被改变:其指针变成null。任何对该元素的使用企图将导致运行时崩溃。任何时候,只要拷贝容器元素,这种情况都有可能发生。记住,即使代码没有进行显式的拷贝或赋值操作,许多算法如:swap()、random_shuffle()、 sort()……会创建一个或多个容器元素的临时拷贝。此外,某些容器的成员函数可能会创建一个或多个元素的临时拷贝。从而使原来的对象变成无效对象。任何并发的对容器元素的操作企图因此而变成了不明确的或者说未定义的行为。
     个别Visual C++ 程序员说他们在STL容器中使用auto_ptr时从来没有遇到过任何问题。告诉你吧,这是暂时的,因为Visual C++ (所有版本)的 auto_ptr 实现都将过期,所依赖的规范都将作废。只要微软决定向最新的ANSI/ISO C++ 标准靠拢(这已经是大势所趋),并对其标准库作相应修改。那么在STL容器中使用 auto_ptr 的代码将出现严重故障。
所以,大家一定不要在STL容器中使用 auto_ptr。不管是空指针,还是其它代替auto_ptr 的智能指针类(如Boost.org提供的那些类)都应该如此。