You are not logged in.
Hey all--
I'm creating a C++ class for a circular array. (The Standard Template Library does not define one.) Most container classes in STL don't require you to call a constructor, and of course constructors return pointers, which means you either have to use placement new or dereference the return value of the constructor or suck it up and use pointers.
Clearly, there's a way to do this, since the STL does it. I could lift the technique from the STL, except it tends to be complex and unreadable and poorly indented. Besides which, for instance in the STL deques, the comments on the deque class claim that the associate _Base class initializes the memory, whereas the comments on the _Base class claim that it doesn't, and I see nothing in either that would do so.
All I want to do is set a couple of default values and allocate some memory. Anyone know how?
It's my fault.
Offline
If you mean that the STL doesn't call the constructor of the type in the template, like vector<string>, the string constructor isn't called, then: I believe it is done by using STL's allocator template class.
Offline
I do not understand the question... *Default* constructor is called whn you write
vector<int> vi;
Offline
Ok, I need to clarify alot of this:
Most container classes in STL don't require you to call a constructor
False. Constructors are always called. C++ is not java and does not require () for a default (or empty) consructor.
and of course constructors return pointers
No. They do not. Constructors initialize an object of already allocated memory. new returns a pointer, malloc returns a pointer, many things return a pointer.. constructors do not.
which means you either have to use placement new or dereference the return value of the constructor or suck it up and use pointers.
this doesn't make sense.
All I want to do is set a couple of default values and allocate some memory. Anyone know how?
const int DEFAULT_ALLOC_SIZE = 32;
template <typename>
class Foo
{
T* t;
public:
Foo() : t(new T[DEFAULT_ALLOC_SIZE]) {}
Foo(int n) : t(new T[n]) {}
};
Foo f; //32 elements
Foo g(10); //10 elements
Offline
A circular array is an array, but not all the arrays are circular arrays. This is the relation you can easily make with a derivation. Make a new class derivated from vector (just study vector's template parameters) and reimplement iterators and some operators.
In a circular array you have no difference between .operator[]() and .at(). You always have to check the limits (as usually only .at does) and instead of throwing a exception calculate the right position:
In this little explamples 'position' is an int with the asked position,'size' is an int with current size of the vector.
if position is non negative the right position is:
position = position % size
if position is negative the right position is:
while (position < 0) position += size
about ++ and -- in the iterators:
++
position = (position +1) % size
--
position = (position + size -1) % size //The sum is there to avoid problems with 0
Probably you want override the operator[] also of iterators...
This way you remplement only few metods and you are there. Moreover you won't have problems of memory leaks, pointers, and (sorry) bugs related to your strange knownledge of C++,
About the main question of the topic that does not make sense IMO since you should do as I told. If you dislike the right and elegant phrakture's solution you can just using new to allocate 'chars' (sizeof(chars) == 1), reinterpret_cast to the type you want and call the costructor when you want.
Offline
A circular array is an array, but not all the arrays are circular arrays. This is the relation you can easily make with a derivation. Make a new class derivated from vector (just study vector's template parameters) and reimplement iterators and some operators.
Avoid inheriting from STL containers, they have non-virtual destructor what may cause problem in certain situations when you only have a pointer to vector, then destructor of derived class will not be called.
Offline
Avoid inheriting from STL containers, they have non-virtual destructor what may cause problem in certain situations when you only have a pointer to vector, then destructor of derived class will not be called.
Yes. Standard Library containers are not meant to be base classes. If you need "circular" access to, say, a vector, one can easilly do:
template <typename> //phpbb is removing "typename ContainerT"
ContainerT::iterator circular_next(ContainerT& container, ContainerT::iterator& it)
{
++it;
if(it == container.end()) it = container.begin();
return it;
}
...
std::vector<int> vec(10,1);
std::vector<int>::iterator it = vec.begin();
for(int i=0; i<100; ++i)
{
std::cout << *it << std::endl;
it = circular_next(vec, it);
}
NOTE: that function works with any standard library container
Offline
OPS... Sorry, I forgot vectors do not use virtual members. Maybe u can still privately hinerit?
Offline
You should _never_ derive from standard library containers. This is not java. Not everything needs a base class of a base class.
While, in some cases, it may be safe to do it, it is poor form. If you need a class that acts-like a vector, use the "has-a" idiom in place of the "is-a" idiom, or simply create your own using the standard container concept.
Decent article on the topic is here:
http://uk.builder.com/programming/c/0,3 … 440,00.htm
But still, why would you create a new class when the function I defined above is 5 lines of code and works for ALL standard library containers... you could have a circular std::map<std> if you wanted to.
Offline