具有std :: unique_ptr的容器的访问器函数

Tec*_*ton 6 c++ api smart-pointers

我即将设计一个存在两个类的API:数据/计算类和此类的容器.然而,容器不仅仅是一个愚蠢的容器,而且还包含整个集合的信息,这超出了可以用迭代器实现的通常的东西.

因此,容器基本上包装了一个std::vector,添加了一些预先计算的属性,实用程序函数等.容器类的API也应该包含的是

  1. 一种添加data/calc类实例的方法,
  2. 存取方法.

我不只是想向std::vector公众开放,因为向容器添加新的数据/计算类会导致重新计算集合类的许多属性.我想,但是,提供访问方法等同于STL容器的存取方法at()operator [].

最初,我添加了该类型的私有属性std::vector<std::unique_ptr<DataClass>>.addDataObject(DataObject *d)存在一种方法,它将对象包装在一起unique_ptr并更新统计信息.

然而,问题在于访问器方法:它们的返回类型是什么?

  • 简单地返回std::unique_ptr<DataClass> &似乎不是一个干净的API设计:API的用户不需要知道我使用智能指针.(另见Herb Sutter关于C++ 11的演讲)
  • 返回DataClass *&是不可能的,尤其不适用operator [],因为我只能std::unique_ptr使用智能指针的get()方法访问一个原始指针,这不会给我一个参考.
  • 返回DataClass &似乎没有意义,特别是当我存储指针(堆与堆栈分配)时.
  • 返回DataClass *会违反最少惊喜的princpile,因为如果一个方法是在STL容器访问器方法的意义上命名的,那么人们会期望它返回一个引用,特别是对于operator [].

作为一个例子,这将是一个简化的例子:

class DataClass
{
    Container *m_parent;
    /* ... other member attributes/parameters ... */
public:

     /* A method that calculates something based on the attributes: */
     double someComplicatedCalculation(const double &input);
};


class Container
{
     std::vector<std::unique_ptr<DataClass>> m_collection;

     /* more attributes: maintenance info, precomputed values, etc. */

  public:

      void addDataObject(DataClass *d);

      /* What would the right return type be? */

      DataClass *&at(const int &index);
      const DataClass *&at(const int &index) const;
      DataClass *&operator [](const int &index);
      const DataClass *&operator [](const int &index) const;
};
Run Code Online (Sandbox Code Playgroud)

Gal*_*lik 1

当您不了解所有细节时,这总是很困难,但我认为:

  • 简单地返回std::unique_ptr<DataClass> &似乎不是一个干净的 API 设计:API 的用户不需要知道我使用智能指针。(另请参阅 Herb Sutter 关于 C++11 的演示)

绝对是的。

  • 返回DataClass *&是不可能的,尤其是 for operator [],因为我只能 std::unique_ptr使用智能指针的get()方法访问 an 的原始指针,这不会给我一个引用。

的确。

  • 返回DataClass &似乎没有意义,特别是当我存储指针(堆与堆栈分配)时。

这确实有道理。我认为一开始就存储指针可能没有意义。无论如何, Astd::vector将所有内容存储在堆上,因此如果这是使用指针的原因,则它不适用。

  • 返回DataClass *会违反最小意外原则,因为如果一个方法是在 STL 容器访问器方法的意义上命名的,那么人们会期望它返回一个引用,特别是对于operator [].

的确。

我想说你应该回来DataClass&。也许你不应该在你的中使用指针std::vector,但如果你必须使用它们,你可以让你的访问器像:

DataClass& operator[](std::size_t index)
{
    return *m_collection[index];
}
Run Code Online (Sandbox Code Playgroud)

但最好不要使用指针:

class Container
{
     std::vector<DataClass> m_collection;

    DataClass& operator[](std::size_t index)
    {
        return m_collection[index];
    }

    // ...
};
Run Code Online (Sandbox Code Playgroud)

  • @Technaton我想你必须权衡复制对象的费用与访问它们的费用以及管理它们的复杂性。另一种可能性(如果系统允许)是提供一个 `emplace()` 样式函数,您可以向容器提供 `DataClass` 构造函数参数,然后 `std::vector` 可以就地构造对象。 (2认同)