Internationalization Module User’s Guide : Chapter 3 Character and String Processing : Representing Strings : Memory Management in RWBasicUString
Memory Management in RWBasicUString
In typical usage, an RWBasicUString instance owns and manages the memory required to hold an array of RWUChar16 values. Like RWCString, RWBasicUString normally copies input data to an internal buffer. This usage is both safe and convenient.
In some cases, however, such as constant strings or large strings, it may be more efficient to avoid this initial copy by having RWBasicUString use an externally-supplied buffer. Therefore, RWBasicUString can also be constructed with two alternate memory management strategies:
An RWBasicUString instance can reference an external buffer in a read-only fashion. In this case, a client supplies the constructor with a Duration value of Persistent. Any attempt to modify the external buffer causes RWBasicUString to copy its contents to an internal buffer. This strategy is primarily used to treat static arrays or arrays of some other long storage duration as RWBasicUString instances. For example:
 
// At file scope
static RWUChar16 acronym = [ 0x0052, 0x0057, 0x0000 ];
 
RWBasicUString
getAcronymAsUString()
{
return RWBasicUString(acronym, RWBasicUString::Persistent);
}
An RWBasicUString instance can assume ownership of an external buffer, and use it in a read-write fashion. To pass ownership of a buffer to an RWBasicUString, a client supplies the RWBasicUString constructor with an RWBasicUString::Deallocator object that can be used to deallocate the buffer. (See “Creating and Using Deallocators”.) This strategy is reminiscent of that offered by std::auto_ptr<T>, except that RWBasicUString implements copy construction and assignment via reference counting. An RWBasicUString mutator modifies the external buffer directly if its capacity is large enough. Otherwise, the mutator copies the buffer's contents to an internal buffer, deallocates the external buffer, then modifies the internal buffer.
Note that in both cases, although the client’s choice of constructor determines the initial memory management strategy, RWBasicUString will abandon an externally-supplied buffer in favor of an internal buffer as necessary.
Creating and Using Deallocators
Passing ownership of a buffer to an RWBasicUString involves supplying the RWBasicUString with an RWBasicUString::Deallocator object. RWBasicUString::Deallocator is an abstract base class that cannot be instantiated directly. Instead, a deallocator can be created in one of two ways:
Create an instance of RWBasicUString::StaticDeallocator, which derives from RWBasicUString::Deallocator.
An RWBasicUString::StaticDeallocator object wraps a pointer to a class static method or a global function. As a convenience, RWBasicUString supplies three such functions: USE_DELETE(), USE_FREE(), and USE_NONE(). For example, the following code creates an RWBasicUString::StaticDeallocator that invokes delete[] to deallocate string buffers. These buffers are returned from a third-party library that allocates buffers via new:
 
// Create a deallocator. It will be re-used by multiple
// RWBasicUString instances.
RWBasicUString::StaticDeallocator
deallocator(RWBasicUString::USE_DELETE);
 
// Return RWBasicUStrings that reference externally-supplied
// buffers.
RWBasicUString
getStringFromOutsideSource()
{
RWUChar16 *array = callToOutsideSource();
return RWBasicUString(array, &deallocator);
}
Create an instance of a custom RWBasicUString::Deallocator subclass.
The subclass can deallocate string buffers in the manner of its choice, to match the manner in which the buffers are allocated.
The use of RWBasicUString::StaticDeallocator allows the client to choose delete[], free(), or custom memory-management mechanisms. The use of an externally supplied deallocation method can also be used to satisfy the heap management requirements of MS-Windows dynamic linked libraries, which in some situations may create their own heap in addition to that of the calling process.
Null Termination
Given sufficient capacity, RWBasicUString adds a null terminator to any non-static array passed to it. This terminating null is not considered part of the contents, and is not included in the count returned by length().