Storing Your Data in C++ Standard Library Containers
If you've worked with some of the newer high-level languages such as Python or PHP, you might have become a tad bit jealous at some of the fancy data structures available in those languages. For example, Python includes a handy list structure that you can put pretty much anything in. Even better, the structure is built right into the syntax of the language. Such structures that hold other data are called containers. An array is a very simple example of a container.
C++, on the other hand, has its roots in C, which was a low-level language. As a result, we still don't have any high-level containers built right into the language syntax beyond simple arrays. But thanks to the ability to essentially extend the language by writing sophisticated data structures, we do have at our disposal several standard classes that serve as containers. As of 1998, these container classes are officially part of the language, even though they're not part of the syntax. Rather, they're part of the official Standard Library.
But unlike languages such as Python, when you create container in C++, you can't just put anything you want inside the container. Instead, when you create the container you specify what datatypes the container can hold. This is because, unlike other modern languages, C++ is strongly typed.
Introducing the Vector
The vector is one of the simplest containers in the Standard Library. Think of it as a souped-up array. You can store items in it just as you can in an array, except that you can manage this task more easily than with an array. Before I show you an example of a vector, however, I need to warn you: The Standard Library makes heavy use of C++ templates. If you're familiar with templates, you can skip to the next section. If you're not familiar with templates, let me give you the 60-second rundown. Templates are not as hard to understand as people make them out to be. A template is simply a cookie cutter for a class. When you use a template, you create a new class based on a template.
For example, you might have a template for a class that holds a single public member variable. This template serves as a cookie cutter by which you can create a new class. But that's boring. To liven it up a bit, let's say that the template can allow you to specify the member variable's datatype when you make your new class based on the template. Get it? The template is a cookie cutter for a class, allowing you to customize the class you're cookie-cutting.
Here's a sample template that shows this concept:
template <typename T> class CookieCutter { public: T x; };
This code isn't a class! It may look like a class, but really it's a template that you can use to create a class. The first line specifies that I have a template, and the stuff inside angle brackets says that I'll specify a type for T later on, when I create a class. The public member x doesn't have a real type yet; it just has the filler name T.
Here's a program that demonstrates how to create a class based on this new template:
#include <iostream> #include <string> using namespace std; template <typename T> class CookieCutter { public: T x; }; int main() { CookieCutter<int> inst; inst.x = 10; cout << inst.x << endl; CookieCutter<string> inst2; inst2.x = "hello"; cout << inst2.x << endl; }
Inside main, it looks like I'm creating an instance of CookieCutter. But I'm not. Instead, I'm creating an instance of a class called CookieCutter<int>. That's a class that the compiler will create based on the template called CookieCutter, using the type int for the T part of the template. Thus, in the class CookieCutter<int>, the public member x is an integer. The member is an integer in the next line, where I save 10 in the member. Next, I print out the value. Then I create an instance of a different class, this time CookieCutter<string>. This is a separate class from CookieCutter<int>, and this time the public member x is type string. You can verify this fact, because I save a string, hello, inside the member, and print it out. Thus, from this one template, I created two separate classes, CookieCutter<int> and CookieCutter<string>.
Before I move on, I want to point out one important little tidbit about C++. Notice that I used the keyword typename in the first line of my CookieCutter template. If you prefer, you can instead use the keyword class in place of typename. It means the same thing in this context. Either is fine and they both work the same. Most people use the keyword class, but I prefer the keyword typename because it doesn't really make logical sense to say class when you're planning to specify types (such as int) that aren't classes. But that's just personal preference; use whichever you want. They work the same.