Provide a reference to a const
string.
More...
Detailed Description
- Outline
-
-
- Purpose:
- Provide a reference to a
const
string.
-
- Classes:
-
- See also:
- Component bdlb_stringrefutil
-
- Description:
- This component defines two classes,
bslstl::StringRef
and bslstl::StringRefWide
, each providing a reference to a non-modifiable string value having an external representation. The type of characters in the string value can be either char
(for bslstl::StringRef
) or wchar_t
(for bslstl::StringRefWide
).
- The invariant of
bslstl::StringRef
is that it always has a valid non-modifiable std::string
value, where non-empty string values have an external representation. Empty string values do not need to have an external representation. Most operations on bslstl::StringRef
objects have reference semantics and apply to the string value: e.g., operator==
compares string values, not whether bslstl::StringRef
objects reference the same string object.
- The only operations that do not apply to the string value (i.e., that have pointer semantics) are copy construction and assignment. These operations produce a
bslstl::StringRef
object with the same external representation as the original bslstl::StringRef
object, which is a stronger post-condition than having operator==
return true
for two bslstl::StringRef
objects that have the same value.
- The standard notion of substitutability defined by the
operator==
does not necessarily apply to bslstl::StringRef
since bslstl::StringRef
is not a value-semantic type (because of the external representation). Therefore there can be a plausible sequence of operations applied to two "equal" bslstl::StringRef
objects that result in objects that don't compare equal.
- The string value that is represented by a
bslstl::StringRef
object need not be null-terminated. Moreover, the string may contain embedded null characters. As such, the string referenced by bslstl::StringRef
, in general, is not a C-style string. Moreover, the notion of a null-string value is not supported.
- The address of the string referenced by
bslstl::StringRef
is indicated by the data
accessor. Its extent is indicated by the length
and size
accessors. The referenced string is also indicated by the begin
and end
accessors that return STL-compatible iterators to the beginning of the string and one character past the end of the string, respectively. An overloaded operator[]
is also provided for direct by-index access to individual characters in the string.
- Several overloaded free operators are provided for
bslstl::StringRef
objects (as well as variants for all combinations involving bslstl::StringRef
and std::string
, and bslstl::StringRef
and char *
) for (1) lexicographic comparison of values, and (2) concatenation of values (producing an std::string
); also provided is an overloaded free operator<<
for writing the value of a bslstl::StringRef
object to a specified output stream.
- The
bsl::hash
template class is specialized for bslstl::StringRef
to enable the use of bslstl::StringRef
with STL hash containers (e.g., bsl::unordered_set
and bsl::unordered_map
).
-
- How to include bslstl::StringRef:
- To include
bslstl::StringRef
use #include <bsl_string.h>
(not #include <bslstl_stringref.h>
).
-
- Efficiency and Usage Considerations:
- Using
bslstl::StringRef
to pass strings as function arguments can be considerably more efficient than passing bsl::string
objects by const
reference. First, consider a hypothetical class method in which the parameter is a reference to a non-modifiable bsl::string
: void MyClass::setLabel(const bsl::string& label)
{
d_label = label;
}
Then, consider a typical call to this method: MyClass myClassObj;
myClassObj.setLabel("hello");
As a side-effect of this call, a temporary bsl::string
containing a copy of "hello" is created (using the default allocator), that value is copied to d_label
, and the temporary is eventually destroyed. The call thus requires the string data to be copied twice (as well as a possible allocation and deallocation).
- Next, consider the same method taking a reference to a non-modifiable
bslstl::StringRef
: Now: myClassObj.setLabel("hello");
This call has the side-effect of creating a temporary bslstl::StringRef
object, which is likely to be more efficient than creating a temporary bsl::string
(even when implemented using the short-string optimization). In this case, instead of copying the contents of "hello", the address of the literal string is copied. In addition, bsl::strlen
is applied to the string in order to locate its end. There are no allocations done on behalf of the temporary object.
-
- Caveats:
- 1) The string referenced by
bslstl::StringRef
need not be null-terminated, and, in fact, may contain embedded null characters. Thus, it is generally not valid to pass the address returned by the data
accessor to Standard C functions that expect a null-terminated string (e.g., std::strlen
, std::strcmp
, etc.).
- 2) The string referenced by
bslstl::StringRef
must remain valid as long as the bslstl::StringRef
references that string. Lifetime issues should be carefully considered when, for example, returning a bslstl::StringRef
object from a function or storing a bslstl::StringRef
object in a container.
- 3) Passing a null string to any function (e.g.,
operator==
) without also passing a 0 length results in undefined behavior.
-
- Usage:
- This section illustrates intended use of this component.
-
- Example 1: Basic Operations:
- The following snippets of code illustrate basic and varied use of the
bslstl::StringRef
class.
- First, we define a function,
getNumBlanks
, that returns the number of blank (' '
) characters contained in the string referenced by a specified bslstl::StringRef
: Notice that the function delegates the work to the std::count
STL algorithm. This delegation is made possible by the STL-compatible iterators provided by the begin
and end
accessors.
- Then, call
getNumBlanks
on a default constructed bslstl::StringRef
: Notice that the behavior a default constructed bslstl::StringRef
object behaves the same as if it referenced an empty string.
- Next, we (implicitly) construct a
bsl::string
object from bslstl::StringRef
: bsl::string empty(emptyRef);
assert(0 == empty.size());
Then, we call getNumBlanks
on a string literal and assert that the number of blanks returned is as expected: numBlanks = getNumBlanks("Good things come to those who wait.");
assert(6 == numBlanks);
Next, we define a longer string literal, poem
, that we will use in the rest of this usage example: const char poem[] =
|....5....|....5....|....5....|....5....|
"O love is the crooked thing,\n"
"There is nobody wise enough\n"
"To find out all that is in it,\n"
"For he would be thinking of love\n"
"Till the stars had run away\n"
"And the shadows eaten the moon.\n"
"Ah, penny, brown penny, brown penny,\n"
"One cannot begin it too soon.";
numBlanks = getNumBlanks(poem);
assert(42 == numBlanks);
Then, we construct a bslstl::StringRef
object, line
, that refers to only the first line of the poem
: bslstl::StringRef line(poem, 29);
numBlanks = getNumBlanks(line);
assert( 5 == numBlanks);
assert(29 == line.length());
assert( 0 == std::strncmp(poem, line.data(), line.length()));
Next, we use the assign
method to make line
refer to the second line of the poem
: line.assign(poem + 29, poem + 57);
numBlanks = getNumBlanks(line);
assert(4 == numBlanks);
assert((57 - 29) == line.length());
assert("There is nobody wise enough\n" == line);
Then, we call getNumBlanks
with a bsl::string
initialized to the contents of the poem
: Next, we make a bslstl::StringRef
object that refers to a string that will be able to hold embedded null characters: char poemWithNulls[512];
const bsl::size_t poemLength = std::strlen(poem);
assert(poemLength < 512);
std::memcpy(poemWithNulls, poem, poemLength + 1);
assert(0 == std::strcmp(poem, poemWithNulls));
Now, we replace each occurrence of a \n
in poemWithNulls
with a yielding \0
: std::replace(poemWithNulls, poemWithNulls + poemLength, '\n', '\0');
assert(0 != std::strcmp(poem, poemWithNulls));
Finally, we observe that poemWithNulls
has the same number of blank characters as the original poem
: numBlanks = getNumBlanks(bslstl::StringRef(poemWithNulls, poemLength));
assert(42 == numBlanks);