Имея вектор weak_ptr, хочу вернуть вектор shared_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() везде я их использую?

6

Решение

Ваша функция — разумное начало:

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, Версия, использующаяtransform пустую shared_ptr в векторе, если истек срок действия слабого_птр.

2

Другие решения

Как насчет:

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

чтобы избежать копирования обратного вектора.

1

Обратите внимание, что 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);

0

Вы могли бы использовать станд :: преобразование

 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(); }
);
0
По вопросам рекламы [email protected]