📄 alloc.html
字号:
to encapsulate pointer types, but does not guarantee that standard containersare functional with allocators using nonstandard pointer types.)Unlike the HP STL, our allocators do not attempt to allow use ofdifferent pointer types. They traffic only in standard void * pointers.There were several reasons for abandoning the HP approach:<UL><LI>It is not really possible to define an alternate notion of pointerwithin C++ without explicit compiler support. Doing so would also requirethe definition of a corresponding "reference" type. But there is no classthat behaves like a reference. The "." field selection operation canonly be applied to a reference. A template function (e.g. max)expecting a T& will usually not work when instantiated with a<I>proxy</i> reference type. Even proxy pointer types are problematic.Constructors require a real this pointer, not a proxy.<LI>Existing STL data structures should usually not be used inenvironmentswhich require very different notions of pointers, e.g. for disk-baseddata structures. A disk-bases set or map would require a data structurethat is much more aware of locality issues. The implementation wouldprobably also have to deal with two different pointer types: real pointers tomemory allocated temporaries and references to disk based objects.Thus even the HP STL notion of encapsulated pointer types would probablybe insufficient.<LI>This leaves compiler supported pointers of different sizes (e.g. DOS/win16"far" pointers). These no longer seem to be of much interest in a generalpurpose library. Win32 no longer makes such distinctions. Neither do anyother modern (i.e. 32- or 64-bit pointer) environments of which we are aware.The issue will probably continue to matter for low end embedded systems,but those typically require somewhat nonstandard programming environmentsin any case. Furthermore, the same template instantiation problemsas above will apply.</ul><H3> There are no allocator objects </h3>An allocator's behavior is completely determined by its type. All data membersof an allocator are static.<P>This means that containers do not need allocator members in order toallocate memory from the proper source.This avoids unneeded space overhead and/or complexity in the container code.<P>It also avoids anumber of tricky questions about memory allocation in operations involvingmultiple containers. For example, it would otherwise be unclear whetherconcatenation of ropes built with two different allocators should beacceptable and if so, which allocator should be used for the result.<P>This is occasionally a significant restriction. For example, it is not possibleto arrange for different containers to allocate memory mapped to differentfiles by passing different allocator instances to the container constructors.Instead one must use one of the following alternatives:<UL><LI> The container classes must be instantiated with different allocators,one for each file. This results in different container types. Thisforces containers that may be mapped to different files to have distinct type,which may be a troublesome restriction, though it also results in compile-timedetection of errors that might otherwise be difficult to diagnose.<LI>The containers can be instantiated with a single allocator, which can beredirected to different files by calling additional member functions.The allocator must be suitably redirected before container calls that mayallocate.</ul><H3>Allocators allocate individual objects</h3>(Shared with standard allocators.)Some C++ programming texts have suggested that individual classes keepa free lists of frequently allocated kinds of objects, so that most allocationrequests can be satisfied from the per-class free list. When an allocationrequest encounters an empty free list, a potentially slower allocator (e.g.new or malloc) is called to allocate several of the required objects at once,which are then used to replenish the free list.<P>The HP STL was designed along these lines. Allocators were intended to beused as the slower backup allocator. Containers like list<T> were presumedto maintain their own free list.<P>Based on some small experiments, this has no performance advantage overdirectly calling the allocate function for individual objects. In fact, thegenerated code is essentially the same. The default allocator we provideis easily inlined. Hence any calling overhead is eliminated. If theobject size is statically known (the case in which per-class free listsmay be presumed to help), the address of the free list header can also bedetermined by the compiler.<P>Per-class free lists do however have many disadvantages:<UL><LI>They introduce fragmentation. Memory in the free list for class <I>A</i> cannotbe reused by another class <I>B</i>, even if only class <I>B</i> objects areallocated for the remainder of program execution. This is particularlyunfortunate if instead of a single class <I>A</i> there are many instancesof a template class each of which has its own free list.<LI>They make it much more difficult to construct thread-safe containers.A class that maintains its own free list must ensure that allocationsfrom different threads on behalf of different containers cannot interferewith each other. This typically means that every class must be awareof the underlying synchronization primitives. If allocators allocateindividual objects, then only allocators themselves need to address thisissue, and most container implementations can be independent of the threadingmechanism.<LI>Garbage collecting allocators are difficult to accommodate. The garbagecollector will see per-class free lists as accessible memory. If pointersin these free objects are not explicitly cleared, anything they referencewill also be retained by the collector, reducing the effectiveness of thecollector, sometimes seriously so.</ul><H3>Deallocate requires size argument</h3>We chose to require an explicit size argument, both for <TT>deallocate</tt>,and to describe the original size of the object in the <TT>reallocate</tt>call. This means that no hidden per-object space overhead is required;small objects use only the space explicitly requested by the client.Thus, even in the absence of fragmentation, space usage is the same as forper-class allocators.<P>This choice also removes some time overhead in the important special caseof fixed-size allocation. In this case, the size of the object, and thusthe address of the free-list header becomes a clearly recognizablecompile-time constant. Thus the generated code should be identical to thatneeded by a per-class free-list allocator, even if the class requiresobjects of only a single size.<H3>We include realloc-style reallocation in the interface</h3>This is probably the most questionable design decision. It wouldhave probably been a bit more useful to provide a version of<I>reallocate</i> that either changed the size of the existing objectwithout copying or returned NULL. This would have made it directlyuseful for objects with copy constructors. It would also have avoidedunnecessary copying in cases in which the original object had not beencompletely filled in.<P>Unfortunately, this would have prohibited use of <TT>realloc</tt> fromthe C library. This in turn would have added complexity to many allocatorimplementations, and would have made interaction with memory-debuggingtools more difficult. Thus we decided against this alternative.<P>The actual version of <TT>reallocate</tt> is still quite useful for container specializations to specific element types.The STL implementation is starting to take advantage of that.</body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -