CPP_STL總結

Overview of the STL
The STL is logically divided into six pieces, each consisting of generic components that interoperate with the rest of the library:

Containers. At the heart of the STL are a collection of container classes, standard C++'s analog to
the CS106B/X ADTs. For example, you can store an associative collection of key/value pairs in an
STL map, or a growing list of elements in an STL vector.

Iterators. Each STL container exports iterators, objects that view and modify ranges of stored
data. Iterators have a common interface, allowing you to write code that operates on data stored
in arbitrary containers.

Algorithms. STL algorithms are functions that operate over ranges of data specified by iterators.
The scope of the STL algorithms is staggering – there are algorithms for searching, sorting, reordering,
permuting, creating, and destroying sets of data.

Adapters. STL adapters are objects which transform an object from one form into another. For example,
the stack adapter transforms a regular vector or list into a LIFO container, while the
istream_iterator transforms a standard C++ stream into an STL iterator.

Functors. Because so much of the STL relies on user-defined callback functions, the STL provides
facilities for creating and modifying functions at runtime. We will defer our discussion of functors
to much later in this text, as they require a fairly nuanced understanding of C++.

Allocators. The STL allows clients of the container classes to customize how memory is allocated
and deallocated, either for diagnostic or performance reasons. While allocators are fascinating
and certainly worthy of discussion, they are beyond the scope of this text and we will not cover
them here.


注:
Here, the containers rely on the allocators for memory and produce iterators. Iterators can then be used
in conjunction with the algorithms. Functors provide special functions for the algorithms, and adapters
can produce functors, iterators, and containers.

一、Vector
1.Vector只能存儲一種類型的元素。
However, while the vector can store elements of any type, any single vector can only
store elements of a single type. It is illegal to create a vector that stores a sequence of many different
types of elements, meaning that you can't represent the list 0, Apple, 2.71828 because each of the list elements
has a different type. This may seem like a rather arbitrary restriction – theoretically speaking,
there's no reason that you shouldn't be able to have lists of all sorts of elements – but fortunately in most
cases this restriction does not pose too much of a problem.
2.Vector定義時需要指定好類型
vector<int> intVector; // Stores ints
vector<string> strVector; // Stores strings
vector<double> realVector; // Stores real numbers
3.使用前需要導入vector頭文件
In order to use the vector type, you will need to #include <vector> at the top of your program. As we
explore some of the other STL containers, this pattern will also apply.
4.size_t的特殊用法
This code is fairly dense and introduces some syntax you have not yet seen before, so let's take a few moments
to walk through exactly how it works. The first detail that might have caught your eye is this one:
for (size_t i = 0; i < v.size(); ++i)
This for loop looks strange for two reasons. First, instead of creating an int variable for the iteration, we
create a variable of type size_t. A size_t is a special type of variable that can hold values that represent
sizes of things (size_t stands for “size type”). In many aspects size_t is like a regular int – it holds an
integer value, can be incremented with ++, compared using the relational operators, etc. However, unlike
regular ints, size_ts cannot store negative values. The intuition behind this idea is that no collection of
elements can have a negative size. You may have a list of no elements, or a list of billions of elements, but
you'll never encounter a list with -1 elements in it. Consequently, when iterating over an STL container, it
is customary to use the special type size_t to explicitly indicate that your iteration variable should always
be nonnegative. The other detail of this for loop is that the loop iterates from 0 to v.size(). The
size() member function on the STL vector returns the number of elements stored in the sequence, just
like the size() and length() functions on the standard string class. In this particular case we could
have iterated from 0 to kNumValues, since we're guaranteed that the main function will produce a vector
of that many elements, but in general when iterating over a vector it's probably a wise idea to use the vector's
size as an upper bound so that the code works for vectors of arbitrarily many elements.
5.容器作爲函數參數時最好作爲引用傳遞,這可以避免拷貝
Consequently, it is considered good programming practice to pass STL containers into functions by reference rather than by value, since this avoids an
expensive copy.*
6.vector的定義需要注意
In some cases, you may want to initialize the vector to a certain size where each element holds a value
other than zero. You may wish, for example, to construct a vector<string> holding five copies of the
string “(none),” or a vector<double> holding twenty copies of the value 137. In these cases, C++ lets
you specify both the number and default value for the elements in the vector using the following syntax:
vector<double> myReals(20, 137.0);
vector<string> myStrings(5, "(none)");
Notice that we've enclosed in parentheses both the number of starting elements in the vector and the value
of these starting elements.
An important detail is that this syntax is only legal when initially creating a vector. If you have an existing
vector and try to use this syntax, you will get a compile-time error. That is, the following code is illegal:
vector<double> myReals;
myReals(20, 137.0); // Error: Only legal to do this when the object is created

7.可以通過resize函數修改vector的定義大小
If you want to change the number of elements in a vector after it has already been created, you can always
use the push_back and insert member functions. However, if you'd like to make an abrupt change
in the number of elements in the vector (perhaps by adding or deleting a large number of elements all at
once), you can use the vector's resize member function. The resize function is very similar to the syntax
we've just encountered: you can specify either a number of elements or a number of elements and a
value, and the vector will be resized to hold that many elements. However, resize behaves somewhat
differently from the previous construct because when using resize, the vector might already contain
elements. Consequently, resize works by adding or removing elements from the end of the vector until
the desired size is reached.

This function takes in a vector<int>, then prints out the elements in the vector one at a time, followed
by a newline. Given this function, consider the following code snippet:
vector<int> myVector; // Defaults to empty vector
PrintVector(myVector); // Output: [nothing]
myVector.resize(10); // Grow the vector, setting new elements to 0
PrintVector(myVector); // Output: 0 0 0 0 0 0 0 0 0 0
myVector.resize(5); // Shrink the vector
PrintVector(myVector); // Output: 0 0 0 0 0
myVector.resize(7, 1); // Grow the vector, setting new elements to 1
PrintVector(myVector); // Output: 0 0 0 0 0 1 1
myVector.resize(1, 7); // The second parameter is effectively ignored.
Because the second argument to resize is only considered if new elements are added, it is effectively
ignored.
PrintVector(myVector); // Output: 0

8.vector中刪除元素的操作
As you saw, the push_back and insert
functions can be used to splice new elements into the vector's sequence. These two functions are balanced
by the pop_back and erase functions. pop_back is the opposite of push_back, and removes the
last element from the vector's sequence. erase is the deletion counterpart to insert, and removes an element
at a particular position from the vector. As with insert, the syntax for erase is a bit tricky. To remove
a single element from a random point in a vector, use the erase method as follows:
myVector.erase(myVector.begin() + n);
where n represents the index of the element to erase.
In some cases, you may feel compelled to completely erase the contents of the vector. In that case, you
can use the clear function, which completely erases the vector contents. clear can be invoked as follows:
myVector.clear();


二、Deque
1.vector支持的操作deque也支持
What's interesting about the deque is that all operations supported by vector are also provided by
deque. Thus we can resize a deque, use the bracket syntax to access individual elements, and erase elements
at arbitrary positions.

2.deque和vector的不同之處,前者速度更快
But this raises an interesting question: if deque has strictly more functionality than vector, why
use vector? The main reason is speed. deques and vectors are implemented in two different ways.
Typically, a vector stores its elements in contiguous memory addresses. deques, on the other hand,
maintain a list of different “pages” that store information. This is shown here:



These different implementations impact the efficiency of the vector and deque operations. In a vector,
because all elements are stored in consecutive locations, it is possible to locate elements through simple
arithmetic: to look up the nth element of a vector, find the address of the first element in the vector, then
jump forward n positions. In a deque this lookup is more complex: the deque has to figure out which page
the element will be stored in, then has to search that page for the proper item. However, inserting elements
at the front of a vector requires the vector to shuffle all existing elements down to make room for
the new element (slow), while doing the same in the deque only requires the deque to rearrange elements
in a single page (fast).
If you're debating about whether to use a vector or a deque in a particular application, you might appreciate
this advice from the C++ ISO Standard (section 23.1.1.2):
vector is the type of sequence that should be used by default... deque is the data structure of
choice when most insertions and deletions take place at the beginning or at the end of the sequence.
If you ever find yourself about to use a vector, check to see what you're doing with it. If you need to optimize
for fast access, keep using a vector. If you're going to be inserting or deleting elements at the beginning
or end of the container frequently, consider using a deque instead.

總結:僅僅是需要快速訪問最好使用vector,假如需要頻繁的在頭部或尾部插入或刪除就使用deque。

3.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章