Re: retrieve size of array
Allan W wrote:
Ron Natalie wrote:
The size of the allocated block (in bytes most likely) must be stored
somewhere. What isn't required is that the memory allocators make that
information available.
Why must the size be stored somewhere?
Suppose I am trying to write a program where speed is an overriding
concern... I don't want it to take 190 seconds to complete, if it's
possible to complete in 189 seconds. And further suppose that I happen
to know that the computer where this system will run has 1 Gigabyte of
physical RAM available, but the grand total of all memory allocations
is expected to be well under 45 Megabytes. Let's also suppose that on
my hardware, cache currency isn't a relevant issue.
I should be able to write my own version of ::operator new, malloc(),
and so on... I believe that (almost?) every compiler supports this. I
could decide to make ::operator delete, free(), and so on, no-op
functions. This is legal, isn't it? And if I do this, is there any
reason why I need to keep track of the sizes of currently-allocated
memory blocks?
This hypothetical example is extremely unlikely, I grant you... but
it's legal, right?
Not so hypothetical example: in CGI programming, it is even desirable
not to free memory explicitly, because it will be freed by the system
when the short-living process exits. The 'allocation' could be done
extremely fast by incrementing pointer to the free memory, and the
size of the block is completely useless and inefficient.
The opposite example: many generic allocators do store the exact size
of the requested block, so it might be wise to reuse it, right?
In particular, if the allocator knows the size of the allocated block,
why does compiler need to overallocate arrays to store the size twice?
Because the compiler is constrained to new/delete interface from the
allocator, which is rather weak for this case.
The same issue could be identified with std::allocator - if it stores
the size already, then it need not to be stored by std::vector. The
implementation of std::vector::capacity() could simply query for
allocator's block size and relax.
Real-life general-purpose systems of course don't work this way...
but my point (I do have one, I'm not just trying to be difficult :-)
is that the memory allocation library is completely independant of
anything that understands what either a C-style array is, or what a
std::vector is.
When the "independence" is the issue, then we might look deeper and
further, and notice that many public interfaces avoid dependence on
std::vector, but prefer C-style arrays, because of their predictable
binary representation. If you need to be binary independent from the
particular STL implementation, you should use C-style arrays. This
contradicts with the recommendation to use std::vector everywhere.
Even more, sometimes it is recommended to depend on a particular
allocator implementation, but not to depend on STL implementation.
If our allocator is known to provide the size-of-block, we can treat
arrays similarly to std::vector - pass them to functions and so on.
To summarize that, a small auto_array_ptr as a replacement for vector:
size_t memory_size(const void* p); // provided by our allocator
template<class T> class auto_array_ptr {
T* p;
public:
explicit auto_array_ptr(T* p = NULL) : p(p) {
}
~auto_array_ptr() {
delete[] p;
}
size_t size() const {
return memory_size(p) / sizeof(T);
}
// other methods like in std::vector<>
};
size_t usage_example(const int* p) // independent from vector
{
auto_array_ptr<int> ap(p);
return ap.size(); // as convenient as vector
}
int main()
{
std::cout << usage_example(new int[168]);
return 0;
}
--
Andrei Polushin
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]