allocate memory 'inside' POD
Hi,
Consider the need for a POD-struct which can store a given number of
double values, where this number is determined at run-time (though then
fixed). The struct itself must not use a pointer type. Access to the
double values shall be possible through members of the POD; moreover,
each POD instance and its associated double values shall cover
contiguous memory; if there is an array of these PODs then the whole
array shall also be in contiguous memory (if you wonder why all that
mess: constraints in a highly heterogeneous environment with multiple
languages and hence compatibility issues).
The snippet below does the job practically speaking, but I am afraid
it's not guaranteed to work according to C++98 / C++03 (these my
implementations refer to). I think that in foo the member 'vals' should
be appropriately aligned so it matches alignment requiresments of a
double array indepenent of the number of elements the array has.
However, according to 5.7/5 I would not be allowed to increment a
pointer to the first element of 'vals' more than once if thispointer has
been obtained through someFoo.vals.
I could treat the bytes at vals and beyond as an array of doubles, but
according to 3.8/2 it seems that a single memory region can only be of
one type at a time; if it's the vals member of a foo object than I can
access it but can't increment the pointer to reach all elements; if it's
interpreted as an array of doubles then technically there would be no
foo object any more and I would not be allowed to access it through the
foo interface.
Any possibility to making it fully C++ compliant while sticking to above
constraints?
thanks!
Thomas
#include <cstdlib>
#include <iostream>
#include <ostream>
#include <new>
struct foo
{
int nVals;
double vals[1]; // here actually nVals values shall occur
};
void print_foo(foo const & Foo)
{
for (int i = 0; i < Foo.nVals; ++i)
std::cout << *(Foo.vals + i) << " ";
}
int main()
{
int nVals = 6; // number of double values per foo object
int nFoos = 3; // number of foo objects to be created
std::size_t fooSize = sizeof(foo);
// extra memory for additional elements
std::size_t extraMemForVals = sizeof(foo().vals[0]) * (nVals - 1);
// memory consumed by foo object with nVals double elements
std::size_t memPerFooWithVals = fooSize + extraMemForVals;
int fooPtrIncrement = memPerFooWithVals / fooSize + (memPerFooWithVals
% fooSize > 0);
// allocate memory
std::size_t memToAlloc = sizeof(foo) * fooPtrIncrement * nFoos;
foo * fooPtr = static_cast<foo *>(::operator new(memToAlloc));
// 'create' nFoos foo objects and initialize their values
for(int i = 0; i < nFoos; ++i)
{
foo * thisFooPtr = fooPtr + i * fooPtrIncrement;
thisFooPtr->nVals = nVals;
double * thisFoovals = &(thisFooPtr->vals[0]);
for (int j = 0; j < nVals; ++j)
thisFoovals[j] = i * 10.0 + j + j / 10.0;
}
// print them
for(int i = 0; i < nFoos; ++i)
{
print_foo(*(fooPtr + i * fooPtrIncrement));
std::cout << std::endl;
}
::operator delete(fooPtr);
}
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]