After a string is created, functions that may grow the string, such as
append() and insert(), will cause a buffer reallocation to
occur if the buffer becomes to small to fit the new string. If you
suspect this is going to happen, you can make things a bit more efficient by
resizing the string buffer yourself ahead of time. As an example, let create a
function that appends random characters to a string. One way to do this is:
void appendRandom(Str& str, unsigned int num_chars) {
char* x = " ";
for (int i=0; i<num_chars; ++i) {
x[0] = (rand() & 0x7F) + 1;
str.append(x);
}
}
The problem is that, if num_chars is large, a lot of buffer
reallocation can take place. Setting str to be TIME_EFFICIENT is
one way to solve the problem but, in this particular case, there is a
better way.
void appendRandom(Str& str, unsigned int num_chars) {
char* x = " ";
str.resize(str.length() + num_chars + 1);
for (int i=0; i<num_chars; ++i) {
x[0] = (rand() & 0x7F) + 1;
str.append(x);
}
}
The call to resize() ensures that str's buffer is large enough to hold the new data
before the append operations begin. Note that, by default,
resize() will not shrink a buffer, only grow it. This means
that, if a different function already made the string large enough or if the
string was based on a large stack or statically-allocated buffer, the resize()
above would have no effect.
But what if you want to reduce string memory usage? By passing a second
parameter of true (i.e. resize(32, true), a programmer
can force a string to reallocate a smaller buffer.
Along these lines, a programmer can call also call compact() on a
string. The compact() function simply calls resize(length() + 1, true).
This is useful for reclaiming a large, empty string buffer.
Note that, for efficiency, compact() and resize(x,true) are the
only two functions that reduce the buffer size of a string. Also note
that calling compact() or resize(x,true) on a string that
is using stack or statically-allocated data will cause the string to switch to heap
data. For this reason, it is a usually good idea to avoid calling these
functions on stack and statically-allocated strings.
To make the rules perfectly clear, here is the resize() logic restated:
resize() will only resize the buffer to grow it
compact(), Str functions always call
resize() using default options.
resize() does resize a buffer, whether it be due to growing
the buffer or a manual override, the new buffer will be created on the heap.
If, during buffer reallocation, STR_ALLOCATED is set then the old
buffer data will be deallocated with free(). If STR_ALLOCATED
is clear, as it should be for stack and statically-allocated data, the old buffer data is
not deallocated but is no longer connected to the string. In either case,
STR_ALLOCATED will be set when the buffer [re]allocation has completed.
length(), the string is
truncated, even if the buffer size is not actually changed. This is not the
best way to truncate a string, however. Use cut() instead.