繁体   English   中英

是使用std :: vector <T*> 不如std :: vector安全 <shared_ptr<T> &gt;?

[英]Is use of std::vector<T*> less safe than std::vector<shared_ptr<T>>?

说我有一个简单的数据类:

struct Foo
{
   int iData;
   double dData;
};

我可以创建一个可以实现为的容器类:

版本1

struct Bar
{
   std::vector<std::shared_ptr<Foo>> fooData;
};

或为:

版本2

struct Bar
{
   Bar(){}

   Bar(Bar const& copy)
   {
      for(auto fooPtr: copy.fooData)
      {
         fooData.push_back(new Foo(*fooPtr));
      }
   }

   ~Bar()
   {
      for(auto fooPtr: fooData)
      {
         delete fooPtr;
      }
   }

   Bar& operator=(Bar const& rhs)
   {
      if ( this == &rhs )
      {
         return *this;
      }

      for(auto fooPtr: fooData)
      {
         delete fooPtr;
      }
      fooPtr.clear();  // Had missed this in the original code.

      for(auto fooPtr: rhs.fooData)
      {
         fooData.push_back(new Foo(*fooPtr));
      }

      return *this;
   }

   std::vector<Foo*> fooData;
};

可以肯定的是, 版本1版本2更容易维护。 但是,我有几个与代码的这一方面正交的问题。

  1. 从处理异常的角度来看, 版本1是否比版本2安全?
  2. 如果是这样,怎么办?

是的,第一种选择更安全。 即,您的副本构造函数有两个内存泄漏源,副本赋值运算符有内存泄漏,这完全是错误的。 此外,默认情况下,第一个选项具有移动分配和移动构造函数,从而提高了性能。 (如果改用std::unique_ptr则性能会更高)

Bar(Bar const& copy)
{
   for(auto fooPtr: copy.fooData)
   {
      fooData.push_back(new Foo(*fooPtr));
      //what happens if `new Foo` throws a bad_alloc?
      //or if `Foo(const Foo&)` changes and now throws something?
      //or if `fooData.push_back` throws a bad_alloc?
      //anything you 'new'd is leaked.
   }
}

Bar& operator=(Bar const& rhs)
{
   if ( this == &rhs )
      return *this;

   for(auto fooPtr: fooData)
      delete fooPtr;
   //You forgot this line:
   //fooData.clear();

   for(auto fooPtr: rhs.fooData) //sharth notes you wrote copy.fooData but that's obvious
      fooData.push_back(new Foo(*fooPtr));
      //what happens if `fooData.push_back` throws a bad_alloc?
      //the `Foo` you just created is leaked.

   return *this;
}

版本1和版本2具有不同的语义。 如果复制Bar对象,则版本1提供对数据的共享访问,而版本2不提供对数据的共享访问。 第2版​​也有微妙的内存泄漏。 如果new成功而push_back失败,则对象泄漏。

为什么不使用更简单的std::vector<Foo> 我没有看到在这种情况下使用指针(共享指针或原始指针)的任何理由。 值语义比指针语义容易得多。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM