Как получить ссылку из буста ptr_vector? - PullRequest
2 голосов
/ 22 сентября 2010

У меня есть два класса: класс Object и класс ObjectManager.Класс ObjectManager хранит «Объекты» через контейнер ptr_vector.В некоторых случаях мне нужно получить ссылки на эти сохраненные указатели, чтобы выполнить с ними отдельные действия.Как мне поступить так?

Скомпилируемый псевдокод:

#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/shared_ptr.hpp>

class Object
{
public:
  int m_Id;
  Object(int id) : m_Id(id) { }
};

class ObjectManager
{
private:
  typedef boost::shared_ptr<Object> ObjectPtr;
  typedef boost::ptr_vector<Object> ObjectVectorPtr;
  typedef ObjectVectorPtr::iterator ObjectIt;

  ObjectVectorPtr vector_;

  void AddObject(Object *obj) {
    vector_.push_back(obj);
  }

  ObjectPtr FindObject(int id) {
    for (ObjectIt it = vector_.begin(); it != vector_.end(); it++) {
      if (it->m_Id == id) {
        // Found the object...How to return a shared_ptr reference to it?
        // The line below is invalid, obviously:
        // cannot convert parameter 1 from 'Object' to 'const boost::shared_ptr<T> &'
        return *it;
      }
    }

    // We could not find anything.
    return ObjectPtr();
  }
};

По сути, я хочу, чтобы ObjectManager сохранил владение, но я также хочу, чтобы другие классы могли получить ссылку наобъект, используйте методы вызова этого объекта в зависимости от того, что происходит, и двигайтесь дальше.

Ответы [ 2 ]

2 голосов
/ 22 сентября 2010

Конвертируйте ваш контейнер, чтобы использовать shared_ptr в качестве члена:

#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/shared_ptr.hpp>
#include <vector>

class Object
{
public:
  int m_Id;
  Object(int id) : m_Id(id) { }
};

class ObjectManager
{
private:
  typedef boost::shared_ptr<Object> ObjectPtr;
  typedef std::vector<ObjectPtr> ObjectVectorPtr;
  typedef ObjectVectorPtr::iterator ObjectIt;

  ObjectVectorPtr vector_;

  void AddObject(ObjectPtr& obj) {
    vector_.push_back(obj);
  }

  ObjectPtr FindObject(int id) {
    for (ObjectIt it = vector_.begin(); it != vector_.end(); ++it) {
      if (it->get()->m_Id == id) {
        // Found the object - return a shared_ptr reference to it
        return ObjectPtr(*it);
      }
    }

    // We could not find anything.
    return ObjectPtr();
  }
};

btw - предпочитайте ++it против it++, чтобы избежать дополнительной конструкции, и не используйте подобное сопоставление, если контейнерстановится большим - переключитесь на std::map<int, ObjectPtr> с m_id в качестве ключа или std :: set с соответствующим образом определенной функцией less.

Если я был супер-педантичным, япредложил бы заменить ваш цикл поиска вызовом std :: find_if с предикатом, совпадающим с Object::m_id ...

0 голосов
/ 22 сентября 2010

Невозможно вернуть shared_ptr, поскольку объект изначально не был создан как общий объект - каким будет счетчик ссылок?

Однако вы можете легко вернуть объект *:

Object* FindObject(int id) {
    for (ObjectIt it = vector_.begin(); it != vector_.end(); it++) {
      if (it->m_Id == id) {
        // Found the object...How to return a shared_ptr reference to it?
        // The line below is invalid, obviously:
        // cannot convert parameter 1 from 'Object' to 'const boost::shared_ptr<T> &'
        return &*it;
      }
    }
...