user3314069
user3314069

Reputation: 33

Does sequential 'new' operators make contiguous allocated memory?

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

Answers (3)

Non-maskable Interrupt
Non-maskable Interrupt

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

Cheers and hth. - Alf
Cheers and hth. - Alf

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.

C++14 (N3936 draft) §5.3.4/10:

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 a new-expression e1 to provide storage for a new-expression e2 if the following would be true were the allocation not extended:
— the evaluation of e1 is sequenced before the evaluation of e2, and
e2 is evaluated whenever e1 obtains storage, and
— both e1 and e2 invoke the same replaceable global allocation function, and
— if the allocation function invoked by e1 and e2 is throwing, any exceptions thrown in the evaluation of either e1 or e2 would be first caught in the same handler, and
— the pointer values produced by e1 and e2 are operands to evaluated delete-expressions, and
— the evaluation of e2 is sequenced before the evaluation of the delete-expression whose operand is the pointer value produced by e1.

Upvotes: 3

catalogue_number
catalogue_number

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

Related Questions