Reputation: 33
I heard std::vector is good because it guarantee contiguous allocated memory (cache-friendly). Then how about sequential 'new' operator like this?
{
new Test1();
new Test2();
new Test3();
}
Does not it make contiguous allocated memory on heap?
Upvotes: 0
Views: 474
Reputation: 3911
On most implementation the allocator would hold previously free'd memory, you would not expect to always get contiguous memory.
Think about this case: Test1
is a large object, Test2
is small one, Test3
is a mid size.
When you allocate for Test1
, the current memory pool don't have large enough reusable memory, so it request to extend the heap and allocate from there.
Then you do for the small Test2
, it's just a tiny object that there is reusable memory from previously free'd one, so you get Test2
from that pool.
For Test3
its similar to Test2
, but for performance the allocator would hold multiple pool for different size-range, so Test3
may not go after Test2
.
NOTE: All these are not mandatory from the specification, it's up to the implementation and what suggested here is just one of the usual implementation (further reading: Buddy memory allocation).
Upvotes: 0
Reputation: 145359
Sequential new
expressions do not necessarily allocate sequential blocks of memory.
But C++14 has special support for such a sequence of new
expressions, where under certain conditions they can be replaced with a single new
expression (that necessarily allocates a sufficiently large chunk of contiguous memory), and where the corresponding delete
expressions are replaced with a single delete
expression.
” An implementation is allowed to omit a call to a replaceable global allocation function (18.6.1.1, 18.6.1.2). When it does so, the storage is instead provided by the implementation or provided by extending the allocation of another
new
-expression. The implementation may extend the allocation of anew
-expressione1
to provide storage for anew
-expressione2
if the following would be true were the allocation not extended:
— the evaluation ofe1
is sequenced before the evaluation ofe2
, and
—e2
is evaluated whenevere1
obtains storage, and
— bothe1
ande2
invoke the same replaceable global allocation function, and
— if the allocation function invoked bye1
ande2
is throwing, any exceptions thrown in the evaluation of eithere1
ore2
would be first caught in the same handler, and
— the pointer values produced bye1
ande2
are operands to evaluateddelete
-expressions, and
— the evaluation ofe2
is sequenced before the evaluation of thedelete
-expression whose operand is the pointer value produced bye1
.
Upvotes: 3
Reputation: 335
Memory management is really up to the operating system - at runtime, this is equivalent to calling the C malloc
function several times in a row, i.e. contiguous allocation is not guaranteed (though likely). To guarantee that the objects are stored in a continuous memory block, they should be kept in an array.
I'm not sure what application you're going for, but in most cases the speed-up from the cache-friendliness is far outweighed by the overhead of passing around objects. cache-friendliness only speeds up programs that are operating on large databases (e.g. mergesort of a long array) because the CPU doesn't need to shuffle the array into and out of cache rapidly - however, for small numbers of objects, you don't have to worry about the cache because its effect will be so tiny. If you're declaring each vector individually, and not as a block in an array, I'm guessing there aren't that many of them, so putting them into an array is not needed and will not speed up your program.
Upvotes: 0