5.3.4 [expr.new]
of the C++11 Feb draft gives the example:
new(2,f) T[5]
results in a call ofoperator new[](sizeof(T)*5+
After reading corresponding standard sections I am satarting to think that placement new for array types is simply useless idea, and the only reason for it being allowed by standard is generic way in which new-operator is described:
The new expression attempts to create an object of the typeid (8.1) or newtypeid to which it is applied. The type of that object is the allocated type. This type shall be a complete object type, but not an abstract class type or array thereof (1.8, 3.9, 10.4). [Note: because references are not objects, references cannot be created by newexpressions. ] [Note: the typeid may be a cvqualified type, in which case the object created by the newexpression has a cvqualified type. ]
new-expression:
::(opt) new new-placement(opt) new-type-id new-initializer(opt)
::(opt) new new-placement(opt) ( type-id ) new-initializer(opt)
new-placement: ( expression-list )
newtypeid:
type-specifier-seq new-declarator(opt)
new-declarator:
ptr-operator new-declarator(opt)
direct-new-declarator
direct-new-declarator:
[ expression ]
direct-new-declarator [ constant-expression ]
new-initializer: ( expression-list(opt) )
To me it seems that array placement new
simply stems from compactness of the definition (all possible uses as one scheme), and it seems there is no good reason for it to be forbidden.
This leaves us in a situation where we have useless operator, which needs memory allocated before it is known how much of it will be needed. The only solutions I see would be to either overallocate memory and hope that compiler will not want more than supplied, or re-allocate memory in overriden array placement new
function/method (which rather defeats the purpose of using array placement new
in the first place).
To answer question pointed out by Kerrek SB: Your example:
void * addr = std::malloc(N * sizeof(T));
T * arr = ::new (addr) T[N]; // #1
is not always correct. In most implementations arr!=addr
(and there are good reasons for it) so your code is not valid, and your buffer will be overrun.
About those "good reasons" - note that you are released by standard creators from some house-keeping when using array new
operator, and array placement new
is no different in this respect. Note that you do not need to inform delete[]
about length of array, so this information must be kept in the array itself. Where? Exactly in this extra memory. Without it delete[]
'ing would require keeping array length separate (as stl does using loops and non-placement new
)