C++ has a string class that behaves very much like the Java String class (but notice that the C++ string class name begins with a lowercase letter). Introducing the string class before exploring classes in general may be a little confusing. However, string objects are an important data type. Presenting them now will allow us to use them as class members when we formally study classes in the next chapter, making our classes more realistic and useful. The early introduction relies on your experience with classes and methods from Java in CS 1400. Furthermore, we'll restrict our treatment of the string class to basic operations and terminology.
Both C++ and Java classes provide one significant advantage over C-strings: once created, a C-string has a maximum length beyond which it cannot grow. The size of the character array storing the C-string limits the C-string's length. Alternatively, instances of both string classes are dynamic and can grow when needed. The ability to grow suggests that string objects can manage their memory. However, in the case of Java, saying that a string can grow is a bit of an oversimplification as Java strings are immutable - they can't change. So, any operation that looks like it modifies a Java string actually creates a new one. Alternatively, When a C++ string needs to grow, it allocates a new, larger array with new, copies the existing data into the new array, and then deallocates the old array with delete. Therefore, growing an already large string can slow a program due to the data copy.
Making string Objects
#include <string>
#include <iostream>
#include <string>
using namespace std;
The string class header file. Any program - or, more accurately, any file in a multi-file program - that uses the string class must include the string header file. When multiple include directives appear in a file, which is quite common, programmers may list them in any order, but they must precede the using statement.
The string class defines ten constructor functions. Programs automatically call constructors whenever they create or instantiate a new object. Constructors can be complex, but often they only initialize the new object. The following table describes three of the most frequently used constructors.
Prototype
Example
Comments
string();
string s1;
Default constructor: builds an empty string
string(const char* s);
string s2("Hello, World!");
Conversion constructor: converts a C-string into a string
string(const string& s);
string s3(s2);
Copy constructor: makes a new string by copying a string
string class constructors. The string class has many constructors, but three do most of the work in day-to-day programming.
One of the many benefits classes provide programmers is hiding the complexity of the class's operations. They do this by separating the operation's interface from its implementation. So, programmers see what the class can do (the function prototypes) but not how it does it (the function bodies). Nevertheless, we can gain some insight into how the string constructors behave by examining the results of a simple program:
string Operators
C++ classes can give new meanings to existing operators, but the new meanings only apply when at least one operand is an instance of the defining class. Assigning a new meaning to an existing operator is called overloading and is the subject of chapter 10.
Operator
Meaning
Example
=
Assignment Converts a C-string to a string
s1 = s2; s = "Hello, World!"
+
Concatenation
s = s1 + s2;
+=
Concatenation with assignment
s += s2
==
Equality
if (s1 == s2) . . .
!=
Inequality
if (s1 != s2) . . .
<, <=, >, >=
Relational
if (s1 < s2) . . .
[] and at()
Character access
char c = s1[i];
<< and >>
Input and output
cout << s1; cin >> s1;
string class operators. The string class overrides many basic C++ operators to make them work with string objects. But it's essential to note that while these operators work with the stringclass, they do not work with C-strings. Furthermore:
at() is a function and not an operator. If s is an instance of the string class, then both s.at(i) and [i] reference the i-th character in string s, but the at function verifies that 0 ≤ i < s.length() while the index operator, [], does not.
Although the extractor operator, >>, works for very simple strings, it does not work for strings that contain spaces or tab characters. The next section presents a more reliable way of entering strings.