std::unique_ptr 容器的访问函数
Accessor functions for containers with std::unique_ptr
我将要设计一个 API,其中存在两个 class:一个 data/calculation class 和一个 class 的容器。然而,容器不仅仅是一个哑容器,它还承载了整个集合的信息,这超出了迭代器可以实现的通常内容。
所以,容器基本上包装了一个std::vector
,添加了一些预先计算的属性,实用函数等。容器class的API也应该包含的是
- 添加实例的方法 data/calc class,
- 访问方法。
我不是单纯的想把std::vector
开到public,因为容器里新加了一个data/calc class导致重新计算集合的一些属性class。但是,我想提供等于 STL 容器访问器方法 at()
和 operator []
.
的访问器方法
最初,我添加了一个 std::vector<std::unique_ptr<DataClass>>
类型的私有属性。存在一个 addDataObject(DataObject *d)
方法,它将对象包装在 unique_ptr
中并更新统计信息。
但是,访问器方法带来了问题:它们的 return 类型是什么?
- 简单地 returning
std::unique_ptr<DataClass> &
似乎不是一个干净的 API 设计: API 的用户不需要知道我使用智能指针. (另请参阅 Herb Sutter 关于 C++11 的演讲)
- 不可能返回
DataClass *&
,尤其是 operator []
,因为我只能使用智能指针的 get()
方法访问 std::unique_ptr
的原始指针,没有给我参考。
- 返回
DataClass &
似乎没有意义,尤其是当我存储指针时(堆与堆栈分配)。
- 返回
DataClass *
会违反最小意外原则,因为如果在 STL 容器访问器方法的意义上命名一个方法,人们会期望它 return 一个引用,尤其是对于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;
};
当你不知道所有细节时总是很困难,但这是我的想法:
- 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 一个指针,你必须在某处指出用户不能删除它。
我将要设计一个 API,其中存在两个 class:一个 data/calculation class 和一个 class 的容器。然而,容器不仅仅是一个哑容器,它还承载了整个集合的信息,这超出了迭代器可以实现的通常内容。
所以,容器基本上包装了一个std::vector
,添加了一些预先计算的属性,实用函数等。容器class的API也应该包含的是
- 添加实例的方法 data/calc class,
- 访问方法。
我不是单纯的想把std::vector
开到public,因为容器里新加了一个data/calc class导致重新计算集合的一些属性class。但是,我想提供等于 STL 容器访问器方法 at()
和 operator []
.
最初,我添加了一个 std::vector<std::unique_ptr<DataClass>>
类型的私有属性。存在一个 addDataObject(DataObject *d)
方法,它将对象包装在 unique_ptr
中并更新统计信息。
但是,访问器方法带来了问题:它们的 return 类型是什么?
- 简单地 returning
std::unique_ptr<DataClass> &
似乎不是一个干净的 API 设计: API 的用户不需要知道我使用智能指针. (另请参阅 Herb Sutter 关于 C++11 的演讲) - 不可能返回
DataClass *&
,尤其是operator []
,因为我只能使用智能指针的get()
方法访问std::unique_ptr
的原始指针,没有给我参考。 - 返回
DataClass &
似乎没有意义,尤其是当我存储指针时(堆与堆栈分配)。 - 返回
DataClass *
会违反最小意外原则,因为如果在 STL 容器访问器方法的意义上命名一个方法,人们会期望它 return 一个引用,尤其是对于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;
};
当你不知道所有细节时总是很困难,但这是我的想法:
- 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 foroperator []
, because I can only access the raw pointer of anstd::unique_ptr
using the smart pointer'sget()
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 foroperator []
.
确实如此。
我会说你应该 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 一个指针,你必须在某处指出用户不能删除它。