std::unique_ptr 容器的访问函数

Accessor functions for containers with std::unique_ptr

我将要设计一个 API,其中存在两个 class:一个 data/calculation class 和一个 class 的容器。然而,容器不仅仅是一个哑容器,它还承载了整个集合的信息,这超出了迭代器可以实现的通常内容。

所以,容器基本上包装了一个std::vector,添加了一些预先计算的属性,实用函数等。容器class的API也应该包含的是

  1. 添加实例的方法 data/calc class,
  2. 访问方法。

我不是单纯的想把std::vector开到public,因为容器里新加了一个data/calc class导致重新计算集合的一些属性class。但是,我想提供等于 STL 容器访问器方法 at()operator [].

的访问器方法

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

但是,访问器方法带来了问题:它们的 return 类型是什么?

作为说明,这将是一个简化的示例:

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

当你不知道所有细节时总是很困难,但这是我的想法:

  • Simply returning std::unique_ptr<DataClass> & doesn't seem to be a clean API design: The user of the API does not need to know I use smart pointers. (See also Herb Sutter's presentation about C++11)

当然可以。

  • Returning DataClass *& isn't possible, especially not for operator [], because I can only access the raw pointer of an std::unique_ptr using the smart pointer's get() method, which does not give me a reference.

确实如此。

  • Returning DataClass & doesn't seem to make sense, especially when I'm storing pointers (heap vs. stack allocation).

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

  • Returning DataClass * would violate the princpile of least surprise, because if a method is named in the sense of the STL container accessor methods, one would expect it to return a reference, especially for operator [].

确实如此。

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

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

但最好不要使用指针:

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

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

    // ...
};

Returning DataClass & doesn't seem to make sense, especially when I'm storing pointers (heap vs. stack allocation).

我不同意。这就是所有标准容器 return。除非你正在使用 unique_ptr 的事实应该对用户可见(我假设它不应该是),否则最不奇怪的方法就是像标准库那样做: return 对象的左值引用。

此外,return参考可以明确所有权。如果你要 return 一个指针,你必须在某处指出用户不能删除它。