我即将设计一个存在两个类的API:数据/计算类和此类的容器。然而,容器不仅仅是一个愚蠢的容器,而且还包含整个集合的信息,这超出了通常可以用迭代器实现的东西。
因此,容器基本上包装了std::vector
,添加了一些预先计算的属性,实用程序函数等。容器类的API也应该包含什么
我不只是想向公众打开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()
的原始指针1}}方法,它没有给我一个参考。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;
};
答案 0 :(得分:2)
返回
DataClass &
似乎没有意义,特别是当我存储指针(堆与堆栈分配)时。
我不同意。这就是所有标准容器的回报。除非您使用unique_ptr
这一事实应该对用户可见(并且我假设它不应该是这样),那么最不惊讶的路径就是像标准库那样做:返回对象的左值引用。
此外,返回引用可以明确所有权。如果要返回指针,则必须指明用户不得删除它。
答案 1 :(得分:1)
当你不知道所有细节时总是很难,但这就是我的想法:
- 简单地返回
std::unique_ptr<DataClass> &
似乎不是一个干净的API设计:API的用户不需要知道我使用 智能指针。 (另见Herb Sutter关于C ++ 11的演讲)
肯定是的。
- 无法返回
DataClass *&
,尤其是operator []
,因为我只能访问原始指针std::unique_ptr
使用智能指针的get()
方法 不要给我一个参考。
确实
- 返回
DataClass &
似乎没有意义,特别是当我存储指针(堆与堆栈分配)时。
这确实有道理。我认为可能没有意义的是存储指针开头。无论如何,std::vector
都会将所有内容存储在堆上,因此,如果这是使用指针的原因,则不适用。
- 返回
DataClass *
会违反最少惊喜的princpile,因为如果一个方法是在STL意义上命名的 容器访问器方法,人们会期望它返回一个引用, 特别是operator []
。
确实
我会说你应该回归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];
}
// ...
};