具有 weak_ptr 的向量,想要返回 shared_ptr 的向量

Having a vector of weak_ptr, want to return a vector of shared_ptr

本文关键字:ptr 向量 返回 shared weak 具有      更新时间:2023-10-16

我目前正在做一个大项目,我需要使用 weak_ptr 而不是 shared_ptr

这是我的问题。

我有一个名为 House 的类,其属性为:vector<boost::shared_ptr<People>> my_people 。我想将此数据成员修改为vector<boost::weak_ptr<People>> my_people

我的吸盘是

vector<boost::shared_ptr<People>>& getPeople() const
{
    return my_people;
}

通常,只需一个简单的weak_ptr我就可以返回my_people.lock();

但是我有一个向量,我不知道如何做这样的事情:

vector<boost::shared_ptr<People>>& getPeople() const
{
    for( vector<boost::weak_ptr<People>::iterator it = my_people.begin();
         it != my_people.end();
         ++it)
    {
        (*it).lock();
    }
    return my_people;
}

换句话说,我想返回我的weak_ptr向量,但作为shared_ptr向量。可能吗?还是我必须返回一个weak_ptr向量并在我使用它们的任何地方使用lock()

你的函数是一个合理的开始:

vector<boost::shared_ptr<People>>& getPeople() const
{
    for( vector<boost::weak_ptr<People>::iterator it = my_people.begin();
         it != my_people.end();
         ++it)
    {
        (*it).lock();
    }
    return my_people;
}

但是调用 (*it).lock() 只会创建一个shared_ptr并将其丢弃,它不会更改矢量元素的类型,并且您不能将矢量作为不同类型的返回。

您需要创建一个正确类型的向量,用shared_ptr对象填充它,然后返回它:

vector<boost::shared_ptr<People>> getPeople() const
{
    vector<boost::shared_ptr<People>> people(my_people.size());
    std::transform(my_people.begin(), my_people.end(), people.begin(),
                   boost::bind(&boost::weak_ptr<People>::lock, _1));
    return people;
}

这会遍历my_people的每个元素,调用lock(),并将结果分配给相应的people元素。

如果您知道my_people永远不会包含过期的指针,那就更容易了:

vector<boost::shared_ptr<People>> getPeople() const
{
  vector<boost::shared_ptr<People>> people(my_people.begin(), my_people.end());
  return people;
}

这通过从weak_ptr元素构造每个shared_ptr元素来填充people向量。 不同之处在于,如果weak_ptr已过期,此版本将引发异常,因为如果传递过期weak_ptr,则shared_ptr构造函数会引发异常。如果转换了过期的weak_ptr,则使用 transform 的版本将在向量中放置一个空shared_ptr

你可以

使用 std::transform

 std::vector<std::shared_ptr<People>> temp;
 sharedTargetList.resize(my_people.size());
 //transform into a shared_ptr vector
 std::transform(my_people.begin(),
        my_people.end(),
        temp.begin(), 
        [](std::weak_ptr<People> weakPtr){ return weakPtr.lock(); } 
 );

怎么样:

vector<boost::shared_ptr<People>> getPeople() const
{
    vector<boost::shared_ptr<People>> res;
    for( vector<boost::weak_ptr<People>::iterator it = my_people.begin(); 
         it != my_people.end(); ++it)
        res.push_back(it->lock());
    return res;
}

此外,如果需要,可以筛选出空指针。

当然,您不能返回对局部变量的引用,因此您必须返回副本。您可能希望改为执行以下操作:

void getPeople(vector<boost::shared_ptr<People>> &res) const
{
    for( vector<boost::weak_ptr<People>::iterator it = my_people.begin(); 
         it != my_people.end(); ++it)
        res.push_back(it->lock());
}

以避免复制返回向量。

请注意,vector<weak_ptr<T> >vector<shared_ptr<T> > 是两种完全不同的类型。

但是,您可以编写一个接受前者并返回后者的函数:

  template<class Ptrs, class WeakPtrs> 
  void lockWeakPtrs(const WeakPtrs &weakPtrs, Ptrs &ptrs)
  {
      BOOST_FOREACH (typename WeakPtrs::const_reference weakPtr, weakPtrs)
      {
          typename Ptrs::value_type ptr = weakPtr.lock();
          if (ptr) // if you want to drop expired weak_ptr's
              ptrs.insert(ptrs.end(), ptr);
      }
  }

像这样打电话: lockWeakPtrs(myWeakVector, mySharedVector);