【问题标题】:Having a vector of weak_ptr, want to return a vector of shared_ptr有一个weak_ptr的向量,想要返回一个shared_ptr的向量
【发布时间】:2012-10-15 12:36:22
【问题描述】:

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

【问题讨论】:

  • 你真的需要weak_ptr吗?

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


【解决方案1】:

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

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_ptrshared_ptr 构造函数将抛出异常。使用transform 的版本如果转换了过期的weak_ptr,则会在向量中放置一个空的shared_ptr

【讨论】:

    【解决方案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(); } 
     );
    

    【讨论】:

      【解决方案3】:

      怎么样:

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

      避免复制返回向量。

      【讨论】:

      • 我想过,但是,我想对属性 my_people 进行操作,而不是对副本进行操作?
      • @user1747056 那么你必须编写一个函数来获取一个特定的向量元素,锁定它,修改它的指针。
      • 你的意思是调用者可以修改(添加/删除)列表吗?如果是这样,恐怕您将需要比这更复杂的东西。例如,您可以在我的答案中拥有一个getPeople(),然后是一个setPeople(const vector&lt;boost::shared_ptr&lt;People&gt;&gt; &amp;ps),它以vector&lt;weak_ptr&gt; 的形式放回修改后的列表。然后,您可以使用辅助类的构造函数/析构函数来包装对getPeople/setPeople 的调用。但我会说你最好继续显而易见:将调用者更改为使用weak_ptr。或者更好的是,不要让调用者修改列表!
      • @rodrigo:调用者经常需要修改列表。我想我要改变调用者使用weak_ptr。我想这是最简单的解决方案。
      • @IgorR。 :它仍然会返回一个副本,不是吗?
      【解决方案4】:

      注意vector&lt;weak_ptr&lt;T&gt; &gt;vector&lt;shared_ptr&lt;T&gt; &gt; 是两种完全不同的类型。

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-08-26
        • 1970-01-01
        • 2017-03-09
        • 1970-01-01
        • 2021-12-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多