Using placement new in a Vector Container
If I have a container:
std::vector<T*> elements;
can I use placement new to allocate my objects so that the objects are all allocate开发者_如何学Pythond contiguously? So that I can do something like this:
size_t elementIndex = someRandomElement - elements[0];
Where someRandomeElement
is a random element from elements
and elementIndex
will then store the correct index of someRandomElement
so that elements[elementIndex] == someRandomElement
This is needed for my current implementation of a memory manager. I have an implementation that I was able to finish today, but it requires the elements (which can be a voxel, a triangle or anything else) to have GetIndex() and SetIndex() function so that when the element is returned as a pointer, I can find out the index of the element in the elements
array, which means that any elements that I cannot change (let's say Ogre::Vector3) cannot use the manager (in my case, I need them to use it because they are fragmenting the memory).
My only other solution is to have a structure that acts as an accessor and has the index as well as the pointer to the element although this will result in an increased memory usage (considering I am working with 5 million elements right now).
NOTE: There is a similar question that I posted today, but the answers there are making some assumptions which go totally against my requirements. One of the requirement is that the vector must be filled with pointers to
T
otherwise a large portion of the code-base needs to change. Secondly, initializing more than 100,000 (approximately) elements results in a bad_alloc exception. Each element is 196 bytes in size (I have managed to reduce that to 132 bytes).
To make your pointed-to objects contiguous, you have two reasonable options:
- use
new[]
to create a single array of elements big enough to hold them all, then assign new values into them and put their addresses into elements - use malloc() to create a big enough uninitialised memory area to hold them all (it will likely be sufficiently-strictly aligned, but you should be aware of the issue), then use placement
new
to construct your elements in that memory
Do not use new[]
then placement new
, as the default-constructed element won't be destructed before placement new overwrites their memory... consequently any resources their constructor takes, counters it maintains etc. can't be properly released/updated by the destructor.
If you don't have enough memory to allocate the big array, then obviously you can't do it... simple as that. 100,000 separate new T
s can be expected to need more memory than a single new T[100000]
though... there's padding and heap management overheads associated with allocation.
The std::bad_alloc
exception is likely because you are attempting to allocate too large a contiguous block of memory. So, consider using a std::deque<T>
instead.
If you decide that you still need a std::vector<T*>
for some reason, you can store pointers to the elements in the std::deque<T>
. As long as you only add and remove elements from the beginning or end of the sequence, you don't need to worry about the pointers being invalidated.
精彩评论