c ++ 11成员函数从unique_ptr的向量返回原始指针的向量

时间:2014-08-26 12:46:27

标签: c++ c++11

我开始使用c ++ 11功能,我喜欢使用智能指针只拥有对象。这是我的班级:

class MyClass {
  public:
    vector<MyObject*> get_objs() const;

  private:
    vector<unique_ptr<MyObject>> m_objs;
};

语义是MyClass拥有一系列MyObject,它们是通过make_unique()创建的。 get_objs()返回原始指针的向量,以便各种调用者更新对象。因为这些调用者不拥有对象,所以函数不会返回vector<unique_ptr>.

但这意味着我需要像这样实施get_objs()

vector<MyObjects*> MyClass::get_objs() const
{
  vector<MyObjects*> ret;
  for (auto obj : my_objs) {
    ret.push_back(obj->get());
  }
  return ret;
}

我关心的是get_objs()经常被调用,每次都有构造这个原始指针向量的开销。

我能在这做些什么吗?如果没有c ++ 11技巧来节省开销,我应该首先在vector<MyObject*>使用m_objs类型吗?

UPDATE 1
使用operator[]的Jonathan Wakely解决方案改进了我的方法,以便调用者可以直接访问单个对象。

还有其他解决方案吗?我不介意去所有调用get_objs(),的地方,但想看看是否有更好的解决方案。

另一个注意事项 - 我不能使用BOOST,只是我必须忍受的一些限制。

5 个答案:

答案 0 :(得分:6)

首先,您可以使用ret.reserve(m_objs.size())预先分配正确数量的元素。

或者,不要为调用者返回一个向量直接迭代的向量,而是显示类似向量的接口:

class MyClass {
  public:
    struct iterator;
    iterator begin();
    iterator end();
    MyObject* operator[](size_t n) { return m_objs[n].get(); }

  private:
    vector<unique_ptr<MyObject>> m_objs;
};

这允许调用者直接修改对象,而不是获取指针容器。

答案 1 :(得分:4)

class MyClass {
  public:
   std::vector<std::unique_ptr<MyObject>> const& get_objs() const {
     return m_objs;
   }

  private:
    std::vector<std::unique_ptr<MyObject>> m_objs;
};

const std::unique_ptr<MyObject>&无法窃取所有权,与std::unique_ptr<const MyObject>不同。 const std::vector<std::unique_ptr<MyObject>>&只能授予const对其数据的访问权限。

答案 2 :(得分:3)

如果您可以使用Boost,请尝试使用indirect_iterator(http://www.boost.org/doc/libs/1_55_0b1/libs/iterator/doc/indirect_iterator.html)。您需要在类中定义迭代器,开始和结束:

typedef boost::indirect_iterator<vector<unique_ptr<MyObject>::iterator> iterator;
iterator begin() { return make_indirect_iterator(m_objs.begin()); }

然后你的类暴露迭代器,其值是MyObject的引用(不是指针!)。您可以直接迭代和访问向量的元素。

答案 3 :(得分:2)

为了记录,我认为像Jonathan Wakely's answer之类的东西是要走的路。但是,由于您要求更多可能性,另一个是使用shared_ptr而不是unique_ptr

class MyClass {
  public:
    const vector<shared_ptr<MyObject>>& get_objs() const {
        return m_objs;
    }

  private:
    vector<shared_ptr<MyObject>> m_objs;
};

这可以通过两种方式改进原始代码:

  1. 不再需要在get_objs中建立新的向量;你可以只返回你所拥有的那个引用。
  2. 在调用者使返回值保持活动的时间长于返回它的对象的情况下,您不再需要担心外部指针 - shared_ptr可确保在所有引用之前不删除指向的对象已被释放。
  3. 另一方面,get_objs可能不应该是const。调用代码不能修改向量本身,但可以修改它包含的MyObject

答案 4 :(得分:0)

另一种方法是根本不返回任何对象并封装您存储数据的方式(告诉不要问)。 通常当你得到这些项目时,你最终都会遍历它们,所以将它包装在类中并传入你希望对象通过的函数是有意义的。

非提升方式将类似于

void MyClass::VisitItems(std::function<void, MyObject&> f)
{
    for (auto obj : my_objs)
    {
        f(*obj);
    }
}