2012-10-15 31 views
6

Tôi hiện đang làm việc trên một dự án lớn và tôi cần sử dụng weak_ptr thay vì shared_ptr.Có vectơ weak_ptr, muốn trả về véc tơ của shared_ptr

Đây là vấn đề của tôi.

Tôi có một lớp có tên Nhà với thuộc tính: vector<boost::shared_ptr<People>> my_people. Tôi muốn sửa đổi thành viên dữ liệu này thành vector<boost::weak_ptr<People>> my_people.

getter của tôi là

vector<boost::shared_ptr<People>>& getPeople() const 
{ 
    return my_people; 
} 

Thông thường, với một đơn giản weak_ptr tôi có thể trở lại my_people.lock();

Nhưng tôi có một vector và tôi không biết làm thế nào để làm một cái gì đó như thế này:

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

Nói cách khác, tôi muốn trả lại véc tơ của mình là weak_ptr nhưng dưới dạng vectơ shared_ptr. Có thể không? Hoặc tôi có phải trả lại véc tơ weak_ptr và sử dụng lock() ở mọi nơi tôi sử dụng chúng không?

+0

Bạn có thực sự cần 'weak_ptr' ở nơi đầu tiên? –

Trả lời

1

gì về:

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

Ngoài ra, bạn có thể lọc ra các con trỏ null, nếu bạn muốn.

Tất nhiên, bạn không thể trả lại tham chiếu đến biến cục bộ để bạn phải trả lại bản sao. Thay vào đó, bạn có thể thực hiện:

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

để tránh sao chép véc tơ trả về.

+0

Tôi nghĩ về điều đó nhưng, tôi muốn thực hiện các thao tác trên thuộc tính my_people, chứ không phải trên một bản sao? – blackmesa

+0

@ user1747056 sau đó bạn phải viết một hàm sẽ lấy một phần tử vector cụ thể, khóa nó, sửa đổi pointee của nó. –

+1

Bạn có nghĩa là người gọi có thể sửa đổi (thêm/xóa) danh sách không? Nếu vậy, tôi sợ rằng bạn sẽ cần một cái gì đó phức tạp hơn thế. Ví dụ, bạn có thể có một 'getPeople()' như trong câu trả lời của tôi, và sau đó là một 'setPeople (const vector > & ps)' đưa trở lại danh sách đã sửa đổi dưới dạng một 'vector ' . Sau đó, bạn có thể bọc các cuộc gọi đến 'getPeople/setPeople' bằng cách sử dụng hàm tạo/destructor của lớp trợ giúp. Nhưng tôi muốn nói rằng bạn nên tiếp tục với điều hiển nhiên: thay đổi người gọi để sử dụng 'weak_ptr'. Hoặc thậm chí tốt hơn, đừng để người gọi sửa đổi danh sách! – rodrigo

0

Lưu ý rằng vector<weak_ptr<T> >vector<shared_ptr<T> > là hai loại hoàn toàn khác nhau.

Tuy nhiên, bạn có thể viết một chức năng chấp nhận các cựu và trả sau:

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

Gọi như thế này: lockWeakPtrs(myWeakVector, mySharedVector);

2

Chức năng của bạn là một sự khởi đầu hợp lý:

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

Nhưng gọi (*it).lock() chỉ cần tạo ra một shared_ptr và ném nó đi, nó không thay đổi t ype của các phần tử vectơ và bạn không thể trả về vectơ dưới dạng một loại khác.

Bạn cần phải tạo một vector của đúng loại, điền vào nó với các đối tượng shared_ptr, và gửi lại:

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

lặp này trên mỗi phần tử của my_people, gọi lock() vào nó, và gán kết quả với phần tử tương ứng của people.

Nếu bạn biết rằng không bao giờ my_people chứa con trỏ hết hạn nó thậm chí còn dễ dàng hơn:

vector<boost::shared_ptr<People>> getPeople() const 
{ 
    vector<boost::shared_ptr<People>> people(my_people.begin(), my_people.end()); 
    return people; 
} 

này lấp đầy people vector bằng cách xây dựng từng phần tử shared_ptr từ một yếu tố weak_ptr. Sự khác biệt là phiên bản này sẽ ném một ngoại lệ nếu weak_ptr đã hết hạn vì trình xây dựng shared_ptr ném nếu đã vượt qua hết hạn weak_ptr. Phiên bản sử dụng transform sẽ đặt shared_ptr trống trong vectơ nếu một weak_ptr hết hạn được chuyển đổi.

0

Bạn có thể sử dụng 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(); } 
); 
Các vấn đề liên quan