Professional C__ - Marc Gregoire [198]
One way to preallocate space is to call reserve(). That method allocates enough memory to hold the specified number of elements. The next section shows an example of the reserve() method in action.
Reserving space for elements changes the capacity, but not the size. That is, it doesn’t actually create elements. Don’t access elements past the vector size.
Another way to preallocate space is to specify, in the constructor or with the resize() method, how many elements you want the vector to store. This method actually creates a vector of that size (and probably of that capacity).
vector Example: A Round-Robin Class
A common problem in computer science is distributing requests among a finite list of resources. For example, a simple operating system could keep a list of processes and assign a time slice (for example 100ms) to each process to let the process perform some of its work. After the time slice is finished, the OS suspends the process and the next process in the list is given a time slice to perform some of its work. One of the simplest algorithmic solutions to this problem is round-robin scheduling. When the time slice of the last process is finished, the scheduler starts over again with the first process. For example, in the case of three processes, the first time slice would go to the first process, the second to the second process, the third to the third process, and the fourth back to the first process. The cycle would continue in this way indefinitely.
Suppose that you decide to write a generic round-robin scheduling class that can be used with any type of resource. The class should support adding and removing resources, and should support cycling through the resources in order to obtain the next one. You could use the STL vector directly, but it’s often helpful to write a wrapper class that provides more directly the functionality you need for your specific application. The following example shows a RoundRobin class template with comments explaining the code. This example uses basic functionality of templates. Templates are introduced in Chapter 11 with a MyArray class template example. Make sure you understand that section first before continuing with this RoundRobin example. Templates are discussed in much more detail in Chapter 19, but for this example, the brief introduction from Chapter 11 is enough to understand it. First, here is the class definition:
// Class template RoundRobin
// Provides simple round-robin semantics for a list of elements.
template class RoundRobin { public: // Client can give a hint as to the number of expected elements for // increased efficiency. RoundRobin(int numExpected = 0); virtual ~RoundRobin(); // Appends elem to the end of the list. May be called // between calls to getNext(). void add(const T& elem); // Removes the first (and only the first) element // in the list that is equal (with operator==) to elem. // May be called between calls to getNext(). void remove(const T& elem); // Returns the next element in the list, starting with the first, // and cycling back to the first when the end of the list is // reached, taking into account elements that are added or removed. T& getNext() throw(std::out_of_range); protected: std::vector typename std::vector private: // Prevent assignment and pass-by-value. RoundRobin(const RoundRobin& src); RoundRobin& operator=(const RoundRobin& rhs); }; Code snippet from RoundRobin\RoundRobin.h As you can see, the public interface is straightforward: only three methods plus the constructor and destructor. The resources are stored in the vector called mElems. The iterator mCurElem always refers to the next element in mElems that should be used in the round-robin scheme. Note the use of the typename keyword in front of the line declaring mCurElem. So far, you’ve only seen that keyword used to specify template parameters, but there is another use for it. You must specify typename explicitly whenever you