6

我目前正在做一个大项目,我需要使用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_ptrlock()在我使用它们的任何地方使用它们?

4

4 回答 4

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()只是创建 ashared_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向量。不同之处在于,如果 a已过期,此版本将抛出异常,因为如果传递了 expired ,构造函数将抛出异常。如果转换过期的weak_ptr,则使用的版本 将在向量中放置一个空。shared_ptrweak_ptrweak_ptrshared_ptrweak_ptrtransformshared_ptr

于 2012-10-15T20:42:59.887 回答
2

你可以使用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(); } 
 );
于 2014-01-07T06:20:48.713 回答
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());
}

以避免复制返回向量。

于 2012-10-15T12:41:03.110 回答
0

请注意,vector<weak_ptr<T> >andvector<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);

于 2012-10-15T12:45:51.547 回答