Vector with references to unique_ptr

拈花ヽ惹草 提交于 2019-12-10 14:55:15

问题


I have a collection of unique_ptrs. Here i want to take some of them and return them to the caller. The caller only needs to read the content, so i wanted to use constant references. But I'm not sure how to do this with unique_ptrs.

Here is some code I used to do this with raw pointers:

class entry
{

};
vector<entry*> master;
const vector<entry*> get_entries()
{
    vector<entry*> entries;
    // peusocode, master contains all entries.
    // only some entries are copied, filtered by some predicate
    copy_if(master.begin(), master.end(), back_inserter(entries), ...);
}

How do I do this with unique_ptrs? I could also use shared_ptr, but the ownership is quite clear and as I mentioned the caller does not need write access.


回答1:


Unique pointer is a "value type" containing a pointer.

So you could treat it as if it is a value type.

But it is uncopyable. So, the solution maybe use const references.

This also can't be applied to "vector" types. So, the solution is to use the reference_wrapper

//type alias for readability
using uEntry = std::unique_ptr<Entry>;

std::vector<uEntry> entries;

std::vector<std::reference_wrapper<const uEntry>> getEntries() {

    std::vector<std::reference_wrapper<const uEntry>> priventries;

    std::for_each(entries.begin(), entries.end(), [&](const uEntry &e) {
        if (e->a > 5) {
            priventries.push_back(std::cref<uEntry>(e));
        }
    });

    return priventries;
}

int main(int argc, const char * argv[]) {
    entries.push_back(uEntry(new Entry(5)));
    entries.push_back(uEntry(new Entry(7)));
    std::cout << getEntries().size();
    return 0;
}



回答2:


The caller only needs to read the content

If the caller won't participate in the ownership of the pointer, then just use raw pointer. In fact, raw pointer can be considered as a pointer without ownership.

std::vector<std::unique_ptr<entry>> master;

std::vector<const entry*>
get_entries()
{
    std::vector<const entry*> entries;

    for ( auto const &ptr : master ) {
        /* if something satisfied */ 
        entries.push_back(ptr.get());
    }
    return entries;
}



回答3:


If you have a vector of unique_ptr and you want to return some of them to the caller you can iterate on the vector and collect raw pointers in another vector and return it. One efficient when you work with smart pointers convention is to use raw pointers for reading, and leave unique_ptr and shared_ptr for memory management

vector<entry*> collect(const vector<unique_ptr<entry>>& data){
    vector<entry*> result;
    for (auto const & it: data){
      if (ShouldBeCollected()){
          result.push_back(it.get())
      }
    }
    return result;    
}

So keep cool and don't delete raw pointers




回答4:


The type of the elements contained by a std::vector must be assignable. References can't be assigned-to (only initialized).


If using raw pointers is not an issue, becasue the caller doesn't take part in the ownership, you could use raw pointers to const entry instead:

vector<const entry *> get_entries();

If you want to use smart pointers, you have to consider that assigning a std::unique_ptr to a std::shared_ptr will transfer the ownership of the pointer. That is, the moved-from std::unique_ptr object becomes empty: it doesn't own a pointer anymore.

Therefore, you may want to consider a complete transition from std::unique_ptr to std::shared_ptr for your collection.




回答5:


By circumstances of OP the solution must look like bellow. I leave to OP how he would apply std::copy_if.

#include <memory>
#include <vector>
#include <algorithm>

class entry {
};

std::vector<std::unique_ptr<entry>> master;

std::vector<const entry*> get_entries()
{
  std::vector<const entry*> entries;
  // only some entries are copied, filtered by some predicate
  std::transform(master.begin(), master.end(), std::back_inserter(entries),
      [](const auto& up){return up.get();});
  return entries;
}


来源:https://stackoverflow.com/questions/48720204/vector-with-references-to-unique-ptr

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!