2012-10-15 63 views
6

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

+0

你真的需要'weak_ptr'摆在首位? –

回答

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

避免复制返回向量。

+0

我想过,但是,我想对属性my_people进行操作,而不是拷贝? – blackmesa

+0

@ user1747056然后你必须编写一个函数,它将采用特定的向量元素,锁定它,修改其指针。 –

+1

您的意思是调用者可以修改(添加/删除)列表吗?如果是这样,恐怕你需要一些比这更复杂的东西。例如,你可以在我的答案中有一个'getPeople()',然后有一个'setPeople(const vector >&ps)''将修改后的列表以'vector ' 。然后,您可以使用助手类的构造函数/析构函数将调用包装到'getPeople/setPeople'中。但我会说你最好用明显的做法:改变调用者使用'weak_ptr'。或者更好,不要让调用者修改列表! – rodrigo

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

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并将其扔掉,它不会改变t y的矢量元素,并且不能将该矢量作为不同的类型返回。

您需要创建正确类型的载体,与shared_ptr对象填充它,并将它返回:超过my_people每个元素

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

这个迭代,调用它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已过期,则此版本将抛出异常,因为shared_ptr构造函数在传递过期weak_ptr时抛出异常。如果转换过期的weak_ptr,则使用transform的版本将在向量中放置一个空的shared_ptr

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(); } 
); 
相关问题