Click Here!
home account info subscribe login search FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
[an error occurred while processing this directive]
Previous Table of Contents Next


Comments

This example used the specialization vector<int>. However, STL containers and algorithms are entirely generic; that is, they are applicable to every data type. This example could have used, for instance, a vector<string> specialization. Furthermore, vector < vector <char> > could have been used to represent a two-dimensional dynamic array.

To see the real strength of generic programming, let’s look at a slightly changed version of the example. This time, use vector<string> specialization. Thus, the vector now stores string objects instead of integers. As you can see, the interface remains the same, regardless of the specialization used.

#include <vector>
#include <iostream>
#include <string>

using namespace std;
void main()
{
  vector <string> vs; //create a vector of strings
  for (;;) //read numbers from a user’s console until “stop” is input
  {
    string temp;
    cout<<”enter a string and press enter; press \”stop\” to terminate” <<endl;
    cin>>temp;
    if (temp == “stop” ) break; //exit from loop?
    vs.push_back(temp); //insert int into the buffer
  }
  cout<< “you entered “<< vs.size() <<” elements into a dynamic vector” << endl;
}//end main

7.2 Read a single element of a container?

Problem

In How-To 7.1, I learned how to insert a new element into a vector. However, I would like to read the value of an existing element from a vector.

Technique

An element in a built-in array can be accessed directly using operator []. Vector overloads the subscript operator, [], enabling by that random access to an element of a vector, as if it were an element of a built-in array. However, vector has an additional method for accessing an element, in the form of the member function at(). at() takes a subscript as an argument, and returns the corresponding element by reference. As you are about to see, the methods differ from one another in two crucial aspects.

Steps

1.  Change to your base source directory and create a new subdirectory named VECTOR_SUBSCRIPT.
2.  Start your source code editor and type the following code into a file named MAIN.CPP.
// this program demonstrates
// two methods of accessing
// a vector element

#include <vector>
#include <iostream>
using namespace std;
void main()
{
  vector <char> vc; //create a vector of chars
  for (int i = 0; i < 10; i++) //fill vc with 10 elements
  {
    char temp = ‘a’ + i; //’a’ ‘b’ ‘c’ etc.
    vc.push_back(temp);
    cout<<”element “<<”[“<< i<<”]” << “ is: “<< vc[i] <<endl;
				   //using subscript operator
    cout<<”element “<<”at”<<” “<< i << “ is: “<< vc.at(i) <<endl;
				   //using at() member function
  }
}//end main
3.  Save MAIN.CPP; next, compile and link MAIN.CPP.
If your compiler complains about the following #include statements:
#include <vector>
#include <iostream>

comment out (or remove) the using directive just below them and change them to read:
#include <iostream.h>
#include <vector.h>
4.  Compile and link the program.
5.  Run the program; the output should be as follows:
element [0] is: a
element at 0 is: a
element [1] is: b
element at 1 is: b
...

and so forth. The final line displays element [9], the letter j.

How It Works

Let us begin by examining the first source line inside main().

vector <char> vc; //create a vector of chars

In this line, an object named vc is declared as a vector of chars.

Next, a for loop is reiterated ten times. First, temp is initialized with the value equivalent to the sum of ‘a’ + i.

for (int i = 0; i < 10; i++) //fill vc with 10 elements
{
  char temp = ‘a’ + i;

Then use the push_back() member function to store the value of temp in vc.

vc.push_back(temp);

Finally, display the element just inserted into vc using the overloaded subscript operator in the first statement, and the at() member function in the second one:

cout<<”element “<<”[“<< i<<”]” << “ is: “<< vc[i] <<endl; //using subscript
							  //operator
cout<<”element “<<”at”<<” “<< i << “ is: “<< vc.at(i) <<endl; //using at()
							      //member function

Comments

Both function templates and class templates are not truly reused. Rather, the boilerplate code is reduplicated for every specialization used. Using large templates such as STL’s containers and algorithms can lead to a significant increase in the size of the executable, a phenomenon sometimes termed “code bloat.”

Templates behave differently than ordinary inheritance. A member function defined in a base class is not copied to its subclasses. Rather, it is shared. Therefore, only a single copy exists, which is accessible to every object instance of this class, as well as any object instance of its subclasses. The following example demonstrates that:

class Base { public: void f();};
void Base::f()
{ cout<<”f”<endl; } } //1
class Derived : public Base {};
Base b;
Derived d;
b.f(); //executes the code defined in //1 above
d.f();//also executes the code defined in //1 above

Another important aspect of templates is their strongly typed nature. Every distinct type also entails a distinct specialization. Thus, if you instantiate a vector<int> and a vector<long> on a machine that represents int and long types as a four-byte unit, you still get two distinct specializations. The same rule applies to the use of signed and unsigned specifiers—vector<unsigned int>, vector<signed int>, and vector<int> are completely different types, so the compiler will expand the template code for each one of these.


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.