Although the above program is simple, it does nothing to show the power
of using Str
. Here is an example that gives a better taste:
void StackExample() { char buff[16]; Str s(buff, sizeof(buff)); // Set a value (< 16 chars) s = "Stack Example"; printf("s = %s\n", (const char*)s); // Set a bigger value (> 16 chars) s = "Stack Overflow Example"; printf("s = %s\n", (const char*)s); }
Here the function specifically assigns the string's data to point to stack
memory. This is much faster than allocating space on the heap. Next a short char*
string is copied into the string s
. This copy is made directly into
buff
on the stack. Next comes the interesting part: A char*
string larger than 16 characters is copied into s
. In the standard
char*
world, this would create a buffer-overflow and lots of associated
problems. But here its not a problem: Str
notices that the new string is
too big to fit in the initial space given to it and automatically allocates an
area on the heap that is large enough.
Whether or not s
has to eventually go to the heap, the s::~Str()
destructor (automatically called) will act appropriately, only freeing heap
data if it needs to. In short, all of the nasty work of dealing with buffer
scenarios is automatically handled but we can still build routines that use the
stack and execute quickly in common cases.
To make things more convienent, a stack-based #define
is included
in Str.hpp
. Instead of defining a stack string with:
char buff[16]; Str s(buff, sizeof(buff));
The following code can be used:
STR(s,16);
The #define
of STR
will expand the second form into the
first. In short, there is no difference what-so-ever to the compiler
which form is used, the results are the same. The difference comes as a
tradeoff between convience and getting away from standard C++ syntax.
In my opinion, the second form has a more compact and conside syntax,
even though it does take advantage of the usually-discouraged preprocessor macro
concept. The final choice is up to you...