Topic: auto_ptr efficiency


Author: paul.black@vf.vodafone.co.uk
Date: 1996/11/19
Raw View
fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) wrote:
> paul.black@vf.vodafone.co.uk writes:
> >Also, if the class has very simple attributes (e.g. all chars) then
> >class new & delete operators might not (and do not need to) provide a
> >block of memory with the same alignment properties as the global
> >operators.
>
> One way of dealing with this is by using template specialization
> to only do this optimization if the size of the object is one
> for which there is a type of that size that requires at least
> two-byte alignment; on most platforms, any object with a non-even
> size will fit this criterion.
>
>  template <class T>
>  class auto_ptr {
>   template <bool can_optimize> class helper;
>   helper<sizeof(T) & 1 == 0> my_helper;
>  public:
>   ...
>  };

There is a problem with this. The alignment requirements of an object are
dependent on the alignment requirements of the attributes of the object and not
the size of the object. There is no automatic way of knowing if
"class auto_ptr<T>::helper<true>" can be used.

Paul

P.S. I guess it's fortunate that "sizeof(T) & 1 == 0" is always false. :-)




[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: fjh@murlibobo.cs.mu.OZ.AU (Fergus Henderson)
Date: 1996/11/20
Raw View
paul.black@vf.vodafone.co.uk writes:

>fjh@mundook.cs.mu.OZ.AU (Fergus Henderson) wrote:
>> One way of dealing with this is by using template specialization
>> to only do this optimization if the size of the object is one
>> for which there is a type of that size that requires at least
>> two-byte alignment; on most platforms, any object with a non-even
>> size will fit this criterion.
>>
>>  template <class T>
>>  class auto_ptr {
>>   template <bool can_optimize> class helper;
>>   helper<sizeof(T) & 1 == 0> my_helper;
>>  public:
>>   ...
>>  };
>
>There is a problem with this. The alignment requirements of an object are
>dependent on the alignment requirements of the attributes of the object and not
>the size of the object.

That is not a problem, because the draft standard (18.4.1.1) requires
new to return memory that is properly aligned for any object of the
specified size, not just for objects of the particular type in
question.  Even if the type is one no alignment requirements, such as
`struct S2 { char s[2]; }' with sizeof(S2) == 2, the expression `new
S2' is required to return memory that is appropriate aligned for any
two-byte object, including `short' if sizeof(short) == 2.  If `short'
has alignment restrictions, then you can safely use that bottom address
bit even for `new S2'.  That was my motivation for the code above.

Oops, 18.4.1.1 only applies to ::new, but auto_ptr might use a
class-specific operator new.  Scrap that previous paragraph.

But even then, on further perusal of the draft I see that your original
claim is highly dubious:

>>>Also, if the class has very simple attributes (e.g. all chars) then
>>>class new & delete operators might not (and do not need to) provide a
>>>block of memory with the same alignment properties as the global
>>>operators.

That's not correct, because all allocation functions must satisfy
the requirements in 3.7.3:

|   3.7.3  Dynamic storage duration                    [basic.stc.dynamic]
|
| 3 Any allocation and/or deallocation functions defined in a C++  program
|   shall conform to the semantics specified in this subclause.
|
|   3.7.3.1  Allocation functions           [basic.stc.dynamic.allocation]
[...]
| 2 The function shall return the address of the start of a block of stor-
|   age whose length in bytes shall be at least as large as the  requested
|   size.  [...]  The pointer returned shall  be  suit-
|   ably  aligned  so that it can be assigned to a pointer of any type and
|   then used to access the object  or  array  in  the  storage  allocated

I think that wording about "can be assigned to a pointer of any type"
comes straight out of the C standard (and incidentally doesn't make
too much sense in C++, since assigning a `void *' to a pointer that
is not a cv-qualified pointer to void will be a type error!).
It seems clear from this that at the very least an allocation of N
bytes must be suitably aligned for any object of size <= N bytes.

So if there is some two-byte type that requires two-byte alignment,
we can change that test to `sizeof(T) > 1'.

>P.S. I guess it's fortunate that "sizeof(T) & 1 == 0" is always false. :-)

Doh!
[The code should be written as `(sizeof(T) & 1) == 0'.]

My mistake, of course, but I do wish K&R had fixed the
precedences while they had the chance.

--
Fergus Henderson <fjh@cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh@128.250.37.3         |     -- the last words of T. S. Garp.


[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]