array new-expressions: proposal

John Wilkinson jfw at cthulhu.engr.sgi.com
Fri Jan 21 19:33:08 UTC 2000


Matt Austern wrote:
> 
> WHAT THE STANDARD SAYS. (3.7.3.1, 5.3.4, and 18.4.1.3)
> 
> Array new has the form "new(ARGS) T[n]".  The "(ARGS)"
> part is optional.  If it's present then this is a placement
> new-expression, and we use a version of operator new[] with
> two or more arguments, otherwise it's an ordinary new-
> expression, and we use a version of operator new[] with one
> argument.  For the purposes of this proposal the distinction
> isn't all that important.
> 
> After finding the appropriate operator new, a new-expression
> obtains storage with
>     void* p = operator new[](n1, ARGS),
> where n1 >= n * sizeof(T).  It then constructs n objects of type
> T starting at position p1, where p1 = p + delta.  The return
> value is p1.
> 
> It is required (3.7.3.1/2) that the return value of any operator
> new[], whether it's built-in or provided by the user, must be
> suitably aligned for objects of any type.
> 
> If T is "char" or "unsigned char" the standard requires that
> delta is a nonnegative multiple of the most stringent alignment
> constraint for objects of size less than or equal to n
> (5.3.4/10).  Otherwise the only restriction is that delta is
> nonnegative.
> 
> Some implementations store the number of elements in the array at
> a negative offset from p1.  The standard neither requires nor
> forbids it.
> 
> There's a predefined placement version of array operator new,
>     ::operator new[](size_t n1, void* p),
> that does nothing but return p.  p must be a pointer to the
> beginning of some array of size at least n1.  The standard
> doesn't tell users how large an array they need.  Many users
> probably assume that it's sufficient for the array to be of size
> n * sizeof(T), but there's no basis in the standard for that
> assumption.
> 
> IA-64 SPECIFICS
> 
> On IA-64 long double is 80 bits.  long double has 128-bit alignment,
> as do classes and unions containing long double, so sizeof(long double)
> is 16.  All other types have 64-bit alignment.
> 
> WHAT THE ABI NEEDS TO SPECIFY
> 
> (1) Given n, and T, what are n1 and delta?
>     (a) Are T=char and T=unsigned char special cases?  (Or,
>         perhaps, is sizeof(T)=1 a special case?)
>     (b) Is ::operator new[](size_t, void*) a special case?
>     (c) Is ::operator new[](size_t), which is used for
>         non-placement new, a special case?
>     (d) Is ::operator new[](size_t, const nothrow_t&) a
>         special case?  I can't find anything in the standard
>         guaranteeing that you can delete an array allocated
>         with nothrow array new using an ordinary array delete-
>         expression, but users probably expect it, and
>         legitimately so.
> (2) Do we store n at a negative offset from p1?  (This affects
>     the answer to question 1.)  If so, we need to specify
>     precisely what that offset is.
> 
> PROPOSAL A.
> 
> No version of operator new[] is a special case.  For any array
> new-expression we store the number of elements in the array,
> as a size_t, at an offset of -sizeof(size_t) from the pointer
> returned by the new-expression.  For any type T other than char,
> unsigned char, long double, or a type containing a long double,
> n1 = n * sizeof(T) + sizeof(size_t).   For those three types,
> since we need to preserve long double alignment, n1 = n * sizeof(T) +
> sizeof(long double).
> 
> Pseudocode for new(ARGS) T[n] under this proposal:
> 
>     if T = char or unsigned char, or if it has long double alignment,
>       padding = sizeof(long double)
>     else
>       padding = sizeof(size_t)
> 
>     p = operator new[](n * sizeof(T) + padding, ARGS)
> 
>     p1 = (T*) (p + padding)
>     ((unsigned long*) p1 - 1) = n
> 
>     for i = [0, n)
>       create a T, using the default constructor, at p1[i]
> 
>     return p1
> 
> PROPOSAL B.
> 
> ::operator new[](size_t, void*) is a special case.  For that
> version of operator new[] only, n1 = n * sizeof(T).  We do not
> store the number of elements in such an array anywhere.
> 
> Pseudocode for new(ARGS) T[n] under this proposal:
> 
>     If the expression is new(p) T[n], and if overload resolution
>     determines we're using ::operator new[](size_t, void*), then
>       p1 = (T*) p
> 
>       for i = [0, n)
>         create a T, using the default constructor, at p1[i]
> 
>       return p1
> 
>     For all other cases, same as proposal A.
> 
> Proposal A is simpler, but proposal B probably conforms more
> closely to user expectations.

After thinking about this for most of the morning, I have concluded that
placement array new is too clumsy to be really useful anyway;  my vote
is for Proposal A.

-- 
John Wilkinson




More information about the cxx-abi-dev mailing list