Data Information, Constructors, and Odds and Ends
Constructors can be described in terms of the effects they have. Because the private portions of a class can be implementation dependent, these effects should be described in terms of information available as part of the public interface. Table F.1 lists several methods whose return values can be used to describe the effects of constructors and of other methods. Note that much of the terminology is from the STL.
Table F.1. Some string Data Methods
Be careful of the differences among begin(), rend(), data(), and c_str(). All relate to the first character in a string, but in different ways. The begin() and rend() methods return iterators, which are generalizations of pointers, as described in Chapter 16, “The string Class and the Standard Template Library.” In particular, begin() returns a model of a forward iterator, and rend() returns a copy of a reverse iterator. Both refer to the actual string managed by the string object. (Because the string class uses dynamic memory allocation, the actual string contents need not be inside the object, so we use the term
string word;
cin >> word;
reverse(word.begin(), word.end());
The data() and c_str() methods, on the other hand, do return ordinary pointers. Furthermore, the returned pointers point to the first element of an
string file("tofu.man");
ofstream outFile(file.c_str());
Similarly, data() and size() could be used with a function that expects to receive a pointer to an array element and a value that represents the number of elements to process:
string vampire("Do not stake me, oh my darling!");
int vlad = byte_check(vampire.data(), vampire.size());
A C++ implementation could choose to represent a string object’s string as a dynamically allocated C-style string and to implement the forward iterator as a char * pointer. In that case, the implementation could choose to have begin(), data(), and c_str() all return the same pointer. But it could just as legitimately (if not as easily) return references to three different data objects.
C++11 has 11 constructors for the basic_string template class, up from the six of C++98, and one destructor:
explicit basic_string(const Allocator& a = Allocator());
basic_string(const charT* s, const Allocator& a = Allocator());
basic_string(const charT* s, size_type n, const Allocator& a = Allocator());
basic_string(const basic_string& str);
basic_string(const basic_string& str, const Allocator&);
basic_string(const basic_string& str, size_type pos,
size_type n = npos, const Allocator& a = Allocator());
basic_string(basic_string&& str) noexcept;
basic_string(const basic_string&& str, const Allocator&);
basic_string(size_type n, charT c, const Allocator& a = Allocator());
template
basic_string(InputIterator begin, InputIterator end,
const Allocator& a = Allocator());
basic_string(initializer_list
~basic_string();
Some of the increase in constructors comes from handling arguments differently. For example, C++98 had this copy constructor:
basic_string(const basic_string& str, size_type pos = 0,
size_type n = npos, const Allocator& a = Allocator());
C++11 replaces it with three constructors—the second, third, and fourth items in the preceding list. This allows the most common uses of the C++98 version to be coded more efficiently. The really new additions are the move constructors (those with rvalue references, as discussed in Chapter 18, “Visiting with the New C++ Standard”) and the constructor with the initializer_list parameter.
Note that most of the constructors have an argument of the following form:
const Allocator& a = Allocator()