Array<N>
, the result is an
Array<N>
, not a Subarray<N>
)
vector
class is recommended as alternative to the
built-in array because it provides index checking and more
features (it can grow dynamically too). Two very different forms
of using it:
vector<int> ivec1(6); // int ivec1[6]; vector<int> ivec2(10, -1); // extra feature, define 10 elements, initialize each to -1 // lacked feature, need extra array to initialize each element of ivec3 int ia[6] = { -2, -1, 0, 1, 2, 1024 }; vector<int> ivec3(ia+1, ia+6); // copy 5 elements of ia into ivec3 vector<int> ivec4(ivec1); // extra feature, initialized with another vector // iterate across elements using subscript operator for (int i=0; i<ivec1.size(); i++) // extra feature // use ivec1[i] as rvalue or lvalue bool isEmpty = ivec.empty(); // extra feature ivec1 = ivec2; // extra feature, assigned to another vector
vector<string> text; // extra feature, define empty vector text.push_back(word); // insert element rather than index and assign // iterate across elements using iterator pair for (vector<string>::iterator it = text.begin(); it!=text.end(); it++) // use *it as rvalue or lvalue
vector<int> ivec1; ivec1[0] = 1024; // error, subscript operator will prompt int ia[7] = { 0, 1, 1, 2, 3, 5, 8 }; vector<int> ivec2(7); for (int i=0; i<ivec1.size(); i++) ivec2.push_back(ia[i]); // add to vector size rather than write over existing elements
An alternative, often preferable solution is to store large or complex class objects indirectly by pointer. The capacity increases, so the number of reallocations drops considerably. Second, the copy and deallocation of a pointer to a class object does not require the invocation of either the copy constructor or the destructor of the class.
Be careful when insert or erase elements of sequential container. They may invalidate current iterator that pointed to particular element of that container. Dereference it can cause invalid pointer read/ write errors or free memory read/ write errors resulting in bad results or crashes.
Adjusting the capacity of simple class vector with default capacity other than 1 seemed to always cause the performance to degrade. On the other hand, increasing the capacity of a large, complex class provided significant performance improvement.
Storing the objects (non built-in data type) directly is considerably less efficient: Each object (and its operands) must be copied onto the stack using copy constructor, then subsequently destroyed. Unless actually modifying the class objects within a container, storing them by pointer is significantly more efficient.
pair
class is part of the standard library
by including <utility>
. It associates
two values of either the same or different types within
a single object. The individual elements of the pair
can be accessed as first
and second
.
class EntrySlot; EntrySlot* look_up(string); typedef pair<string, EntrySlot*> SymbolEntry; SymbolEntry current_entry("author", look_up("author")); // ... if (EntrySlot *it = look_up("editor")) { current_entry.first = "editor"; current_entry.second = it; }
complex
class is part of the standard library
by including <complex>
. It can generally be
intermixed with the built-in data types.
complex<double> c1(3.14159, -2.171); complex<double> c2(c1.real()); int i = 3; complex<double> c3 = i; complex<double> c4 = c1 + 3.14159; double d = c1; // compile-time error double re = real(c2); // nonmember syntax, like cast double im = c2.imag(); c4 += c3; // supported cout << c2 << endl; // "( 3.14159, -2.171 )" cin >> c2; // valid input // 3.14159 ==> complex(3.14159); // (3.14159) ==> complex(3.14159); // ( 3.14, -1.0 ) ==> complex(3.14, -1.0);
map<string, int> word_count; word_count[string("Anna")] = 1;The following steps take place:
word_count
map is searched for the entry
"Anna". The entry is not found.
word_count
.
The key, of course, is a string object holding the value "Anna".
The value, however, is 0 (default value of built-in data type).
word_count.insert(map<string, int>::value_type(string("Anna"), 1)); // or typedef pair<string, int> valType; word_count.insert(valType(string("Anna"), 1));If the instance is not present, the use of the subscript operator causes an instance to be inserted. To discover whether the key is present without its absence causing an instance to be inserted:
count(keyValue)
: return number of occurrences of
keyValue
within map. (For map, the return value
can be only 0 or 1; can be more than 1 for multimap)
int count = 0; if (word_count.count("wrinkles")) count = word_count["wrinkles"]; // can safely use the operator[]
find(keyValue)
: returns an iterator to the
instance within the map if the instance is present or returns an
iterator equal to end()
if the instance is not present.
int count = 0; map<string, int>::iterator it = word_count.find("wrinkles"); if (it != word_count.end()) count = (*it).second; // map iterator point to pair<key, value>
find()
(it points to the first instance) and the value
returned by count()
. (This works because the instances
are guaranteed to occur contiguously within the container)
multimap<string, string> authors; string search_item("Alain de Botton"); multimap<string, string>::iterator iter; iter = authors.find(search_item); int num = authors.count(search_item); for (int cnt=0; cnt<num; cnt++, iter++) do_something(*iter);
equal_range()
. It returns a pair of iterator.
If the value is present, the first iterator points to the first
instance of the value and the second iterator points 1 past the
last instance of the value. If the last instance is the last
element, the second iterator is set equal to end()
.
typedef multimap<string, string>::iterator iterator; pair<iterator, iterator> pos; pos = authors.equal_range(search_item); for ( ; pos.first != pos.second; pos.first++) do_something(*(pos.first));
One constraint on access of an element of a multimap is that the subscript operator is not supported.
Index