有一个weak_ptr的向量,想要返回一个shared_ptr的向量

时间:2012-10-15 12:36:22

标签: c++ boost vector shared-ptr weak-ptr

我目前正在开展一个大型项目,我需要使用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()

4 个答案:

答案 0 :(得分:2)

你的功能是一个合理的开始:

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;
}

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

答案 1 :(得分:1)

怎么样:

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());
}

避免复制返回向量。

答案 2 :(得分:0)

请注意,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);

答案 3 :(得分:0)

您可以使用 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(); } 
 );