处理 stl 容器的大小
我正在重写一个通用库,该库是我在学习 STL 之前编写的。它始终使用 C 风格的数组。很多地方都有这样的代码:
unsigned short maxbuffersize; // Maximum possible size of the buffer. Can be set by user.
unsigned short buffersize; // Current size of the buffer.
T *buffer; // The buffer itself.
我做的第一件事就是把代码改成这样:
unsigned short maxbuffersize;
unsigned short buffersize;
std::vector<T> buffer;
然后:
typedef unsigned short BufferSize;
BufferSize maxbuffersize;
BufferSize buffersize;
std::vector<T> buffer;
然后我觉得我做了一件很糟糕的事情,应该重新考虑我的编码风格。起初,BufferSize 对于一种类型来说似乎是一个非常糟糕的名字,但随后各种奇怪的问题开始出现。如何命名尺寸类型?我应该使用自己的类型还是从 std::vector
继承?我应该缓存容器的大小还是一直使用 size()
?我是否应该允许用户手动设置容器的最大大小,如果不允许,如何检查溢出?
我知道不可能有一种放之四海而皆准的方法,因此我想听听其他编码人员和框架供应商使用的策略。我正在开发的库是跨平台通用的,旨在发布到公共领域并使用数十年。谢谢。
I'm rewriting a general purpose library that was written by me before I've learned STL. It uses C-style arrays all the way. In many places there is a code like this:
unsigned short maxbuffersize; // Maximum possible size of the buffer. Can be set by user.
unsigned short buffersize; // Current size of the buffer.
T *buffer; // The buffer itself.
The first thing I did was to change the code like this:
unsigned short maxbuffersize;
unsigned short buffersize;
std::vector<T> buffer;
And then:
typedef unsigned short BufferSize;
BufferSize maxbuffersize;
BufferSize buffersize;
std::vector<T> buffer;
And then I felt like I was doing a very bad thing and should reconsider my coding style. At first, BufferSize seemed like a very bad name for a type but then all kinds of weird questions started popping up. How do I name the size type? Should I use my own type or inherit from std::vector<T>::size_type
? Should I cache the size of container or use size()
all the way? Should I allow the user to manually set the maximum size of container and if not, how do I check for overflow?
I know that there can't be one-size-fits-all approach therefore I'd like to hear the policies other coders and framework vendors use. The library I'm working on is cross-platform general purpose and is intended to be released into public domain and be used for decades. Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为默认选择应该是摆脱 buffersize 和 maxbuffersize 并使用 buffer.size() 和 buffer。整个过程中的容量()。
我建议不要缓存大小除非您有非常具体的理由这样做,并且有分析器运行的硬数据支持。缓存会带来额外的复杂性以及缓存与真实事物同步的可能性。
最后,在您认为需要进行边界检查的地方,您可以使用 buffer.at(i)。如果
i
超出范围,这将引发异常。I think the default choice ought to be to get rid of both
buffersize
andmaxbuffersize
and usebuffer.size()
andbuffer.capacity()
throughout.I would advise against caching the sizes unless you have very specific reasons to do this, backed with hard data from profiler runs. Caching would introduce extra complexity and the potential for the cache to get of sync with the real thing.
Finally, in places where you feel bounds checking is warranted, you could use
buffer.at(i)
. This will throw an exception ifi
is out of bounds.一般来说,我建议使用迭代器来访问数据。当您这样做时,您通常根本不会显式调用容器的大小。这也使您不再使用
std::vector
,并且可以让您简单地更改为std::list
(如果您后来意识到这更适合您的需求) 。当您使用迭代器时,对
vector.size()
的需求通常会大大减少。(当您确实需要它时,请使用 buffer.size() 和 buffer.capacity(),如 aix 所说)。
例如:
变得
更干净一点。
In general I would advise using iterators to access your data. When you do this you often don't explicitly call the size of the container at all. This also decouples you from using
std::vector
all together - and lets you simply change to, for examplestd::list
if you realize later that this better suits your needs.When you use iterators the need for
vector.size()
in general greatly decreases.(when you do need it use
buffer.size()
andbuffer.capacity()
as aix says).For example:
becomes
which is a little bit cleaner.
保持大小对于可能的结构很有用,但对于数组/向量来说有点多余,因为大小保证是最终索引+1。如果您担心运行超过末尾,那么提到的迭代器方法可以解决这个问题,以及有关可能的比较大小等的大多数其他问题;
使用 API 在标头中定义所有类型及其大小是相当标准的,该 API 将它们设置为不同的平台和编译器...查看 Windows 的 LONG、ULONG、DWORD 等定义。旧的“C”约定就是在它们前面加上唯一的名称或缩写,例如 MYAPI_SIZETYPE。它很啰嗦,但避免了任何跨平台混乱或编译器问题。
Keeping the size is useful for may structures, but it's a bit redundant for arrays/vectors, since the size is guaranteed to be the final index+1. If you are worried about running past the end, an iterator approach such as was mentioned would solve this, as well as most other issues regarding possible sizes for comparisons, etc;
it's pretty standard to define all of your types and their sizes in a header with the API which sets them for different platforms and compilers...look at windows with it's definitions of LONG, ULONG, DWORD, etc. The old "C" convention is to preface them with a unique name or initials such as MYAPI_SIZETYPE. It's wordy but avoids any crossplatform confusion or compiler issues.