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