Re: newbie: ar[1] at end of POD
andrew_nuss@yahoo.com wrote:
Hi,
I am creating pools of small integer arrays. There are individual
allocs from the pool, but
no frees to the pool, and one free for the whole pool. The pool
creates chunks of 10000 elem
arrays. I subdivide the chunk into Snippet as follows:
class Snippet {
friend class SnippetPool;
int ar[1]; // first element is length
// enough room in Snippet object to hold more
elems
// this is the ONLY data member of POD
public:
int length () const
{
return ar[0];
}
int& operator [] (int i)
{
return ar[i+1]; // bounds check omitted
}
};
Strictly speaking, this is not a POD since it have member functions.
{ incorrect. it's not a POD because 'ar' is private. -mod }
If the purpose of such a class is to implement bounds checking then I
would use something like this:
#include <stdexcept>
class Snippet
{
public:
Snippet(int* _begin, size_t _length)
: begin(_begin), length(_length)
{
}
size_t get_length(void) const
{
return length;
}
int& operator[](size_t offset) const
{
if (offset >= length)
throw std::out_of_range(__FUNCTION__);
return begin[offset];
}
private:
int* begin;
size_t length;
};
My question is if I have a large chunk of int*, how do I create
Snippets of length N
from these chunks? Want it to work on all platforms! For example,
class SnippetPool {
// assume that we have one chunk big enough to
// hold all snippets, and destructor throws away chunk
int* buffptr;
int buffcnt;
Snippet* Alloc (int len)
{
len++;
if (len < 1 || len > buffcnt)
throw MyException();
void* p = buffptr;
buffptr += len;
// does the following make assumptions about the C++
// implementation of POD? What's better?
Snippet* s = static_cast<Snippet*>(p);
// set the logical length for caller
// but leave rest of array as garbage
s->ar[0] = len-1;
return s;
}
};
For this class I would use something like:
#include <vector>
class SnippetPool
{
public:
SnippetPool(size_t capacity)
: buffer(capacity), room(capacity)
{
}
Snippet alloc(size_t length)
{
if (length > room)
throw std::bad_alloc(__FUNCTION__);
int* p = &buffer[0] + (buffer.size() - room);
room -= length;
return Snippet(p, length);
}
private:
std::vector< int > buffer;
size_t room;
};
1. Quite portable.
2. Snippet object is returned by value, not by pointer, and may be
copied safely.
3. The buffer elements are initialized upon SnippetPool construction.
The classes may be further generalized using templates if you want.
Simply add
template< typename T >
right before class declarations. And replace 'int' with 'T' where
appropriate.
Alex
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]