2011-10-04 104 views
3

我正在重写一个在学习STL之前由我编写的通用库。它一路使用C风格的数组。在许多地方有这样的代码:处理stl容器的大小

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<T>::size_type继承?我应该缓存容器的大小还是一直使用size()?我应该允许用户手动设置容器的最大尺寸,如果不是,我该如何检查溢出?

我知道不可能有一种万能的方法,因此我想听听其他编码器和框架供应商使用的策略。我正在研究的图书馆是跨平台的通用目的,旨在发布到公共领域并使用数十年。谢谢。

+0

既然你要将它释放到公有领域,我认为你应该给你的程序一点点插件。 – Tom

+0

这是[Source engine console](http://developer.valvesoftware.com/wiki/Console)的克隆,但有一些限制(例如只有一个实例)被删除。 – Lyberta

+0

王牌,如果你在互联网上建立一个仓库(如github) - 发布链接 – Tom

回答

12

我认为默认选择应该是摆脱buffersizemaxbuffersize,并全程使用buffer.size()buffer.capacity()

我建议不要缓存大小,除非您有非常具体的原因来执行此操作,并使用探查器运行的硬数据。缓存会带来额外的复杂性,并且缓存可能与真实事物保持同步。

最后,在您认为有必要进行检查的地方,您可以使用buffer.at(i)。如果i超出范围,这将引发异常。

+0

缓冲“std :: vector”的大小完全是愚蠢的,因为它保证了性能不变(即与元素数量无关)。据我所知(这些包括'std :: array','std :: string','std :: valarray') – rubenvb

+1

@rubenvb真的对于任何其他序列容器也是如此? (for size_t i = 0; i Tom

+0

命名约定呢?我认为BufferSizeType是一个很好的例子,但是有些情况下索引被传递给用户是不透明的,我不知道一个好的方法来解决这个问题。 – Lyberta

2

一般来说,我会建议使用迭代器来访问您的数据。当你这样做时,你通常不会明确地调用容器的大小。这也可以将你从一起使用std::vector中分离出来 - 并且让你简单地改变为例如std::list,如果你稍后意识到这更适合你的需求。

当你使用迭代器时,对vector.size()的需求一般会大大减少。 (当你确实需要它使用buffer.size()buffer.capacity()作为aix说)。

例如:

typedef unsigned short BufferSize; 
BufferSize maxbuffersize; 
BufferSize buffersize; 
std::vector<T> buffer; 
for(unsigned short i = 0; i< maxbuffersize;++i) 
{ 
    //do something with buffer[i]; 
} 

变得

struct do_something 
{ 
    void operator()(const T& t) 
    { 
    //do something with buffer[i] 
    } 
}; 
std::vector<T> buffer(maxbuffersize); 
std::for_each(buffer.begin(), buffer.end(), do_something()); 

这是一点点清洁器。

0

保留大小对于may结构很有用,但对于数组/向量来说有点多余,因为大小保证是最终索引+ 1。如果你担心运行结束,像上面提到的迭代器方法将解决这个问题,以及大多数可能的比较大小等问题;

这是非常标准的定义您的所有类型和它们的大小在一个标头中的API,它为不同的平台和编译器设置它们......查看与它的LONG,ULONG,DWORD等定义的窗口。旧的“C”约定是以一个唯一的名称或首字母缩写(如MYAPI_SIZETYPE)作为前缀。这很罗嗦,但避免了任何跨平台混淆或编译器问题。

+0

我把所有我的类型进入我自己的命名空间,并且从不使用''使用'来避免名称冲突。 – Lyberta