Experience Summary of C + + container usage

Source: Internet
Author: User
Tags bitset data structures

paragraph 1 Chapter Container

paragraph 1 Caution: Select the container type carefully.

Standard STL sequence Containers: Vector, String, deque, and list.

Standard STL Associative containers: Set, Multiset, map, and Multimap.

Non-standard sequence containers slist and rope. Slist is a one-way list, rope is essentially a "heavy" string.

Non-standard associative containers hash_set, Hase_multiset, Hash_map and Hash_multimap.

Vector<char> as a substitute for string. (see article 13th)

Vectors as a substitute for standard associative containers. (see article 23rd)

Several standard non-STL containers, including arrays, Bitset, Valarray, Stack, queue, and priority_queue.

Whether you care about how the elements in the container are sorted. If you don't care, select the hash container.

Whether the layout of the data in the container needs to be compatible with C. If compatibility is required, only vectors can be selected. (see article 16th)

Whether the element's lookup speed is a key consideration. If so, consider the hash container, the vector that is sorted, and the standard associative container-perhaps this is the order of precedence.

Do you need transaction semantics for insert and delete operations? If yes, you can only select list. Because in a standard container, only the list provides transactional semantics for inserting multiple elements.

The deque is unique, the iterator may become invalid (the insertion operation only occurs at the end of the container, the deque iterator may become invalid) and the pointer to the data and the standard STL container that the reference is still valid.

paragraph 2 do not attempt to write code that is independent of the container type.

If you want to write code that works for most containers, you can only use the intersection of their functionality. Different containers are different, and they have very obvious advantages and disadvantages. They are not designed to be exchanged for use.

You cannot write code that is separate from the container, but they may be available (in the case of customer code).

paragraph 3 ensures that the objects in the container are copied correctly and efficiently.

Copy in,copy out, is the way STL works, its overall design idea is to avoid unnecessary copies. An easy way to make the copy action efficient and prevent the split problem from occurring is to make the container contain pointers rather than objects.

paragraph 4 bars: Calling Empty rather than checking size () whether to 0 .

The reason is simple: empty is a constant time operation for all standard containers, and for some list implementations, size consumes linear time.

paragraph 5 the interval member function takes precedence over a single element member function corresponding to it.

Interval member functions are easier to write, express your intentions more clearly, and they show greater efficiency.

paragraph 6 : Beware C + + Compiler The most annoying analysis mechanism.

It is legal to enclose the form in parentheses, which is illegal in parentheses around the declaration of the entire formal parameter, including the data type and the formal parameter name.

paragraph 7 : If the container contains the pass New action creates a pointer to the container object before it is destructor Delete off.

The STL is intelligent, but it is not smart to know whether or not to delete the object to which the pointer it contains is pointing. To avoid resource leaks, you must manually delete each of these pointers before the container is refactored, or use the reference counting form of a smart pointer (such as Boost's sharedprt) to replace the pointer.

paragraph 8 : Never create a containing auto_ptr container object.

Copying a auto_ptr means changing its value. For example, a vector called sort ordering containing auto_ptr results in that several elements of the vector are set to null and the corresponding elements are deleted.

paragraph 9 Caution: Select the method to delete the element.

To delete all objects of the specified value in the container:

If the container is a vector, string, or deque, the Erase-remove idiom is used.

Seqcontainer<int> C;

C.erase (Remove (C.begin (), C.end (), 1963), C.end ());

If the container is a list, use List::remove.

If the container is a standard associative container, its erase member function is used.

To delete all objects in a container that meet certain criteria:

If the container is a vector, string, or deque, the erase-remove_if idiom is used.

If the container is a list, use list::remove_if.

If the container is a standard associative container, use remove_copy_if and swap, or write an element that loops through the container, remembering that when you pass the iterator to the erase, it is incremented.

Assoccontainer<int> C;

...

Assoccontainer<int> goodvalues;

Remove_copy_if (C.begin (), C.end (), Inserter (Goodvalues, Goodvalues.end ()), badvalue);

C.swap (goodvalues);

Or

for (Assoccontainer<int>::iterator i = C.begin (); I!=c.end ();/* do nothing */) {

if (Badvalue (*i)) c.erase (i++);

else ++i;

}

To do something inside a loop (except to delete an object):

If the container is a standard sequence container, write a loop to iterate through the elements in the container, remembering to update the iterator with its return value each time you drop the erase.

If the container is a standard associative container, write a loop to iterate through the elements in the container, remembering that the iterator should be incremented each time the iterator is passed to the erase.

paragraph Ten learn about assigning children (Allocator) of Conventions and restrictions.

paragraph One to understand the rational use of a custom assignment.

paragraph of article: do not STL the thread security of a container is impractical to rely on.

To an STL implementation you can only expect:

It is safe to read multiple threads.

Multiple threads are safe to write to different containers.

You can't expect the STL library to free you from manual sync control, and you can't rely on any thread support.

paragraph 2 Chapter Vector and string

paragraph of article: Vector and string takes precedence over dynamically allocated arrays.

If you use new, it means you have to make sure that the delete is in the back.

If you are using a string that is implemented as a reference count, and you run in a multithreaded environment and think that a string's reference count implementation can affect efficiency, you have at least three possible options, and no option is to discard the STL. First, check your library implementation to see if you can disable the reference count, usually by changing the value of a preprocessing variable. Second, find or develop a string implementation that does not use reference counting. Third, consider using vector<char> instead of string. The vector implementation does not allow reference counting, so hidden multithreaded performance issues do not occur.

paragraph - article: Using Reserve to avoid unnecessary redistribution.

There are usually two ways to use the reserve to avoid unnecessary reallocation. The first way to do this is to use reserve if you know exactly how many elements will eventually be in the container. The second way is to set aside enough space and then, when all the data is added, remove the excess capacity.

paragraph - Note: string realize the diversity.

If you want to use STL effectively, then you need to know the variety of string implementations, especially when you're writing code that has to run on different STL platforms and you're facing stringent performance requirements.

paragraph - article: Learn how to put Vector and string data passed to the old API .

If you have a vector V, and you need to get a pointer to only the data in V, so that you can use the data as an array, you just need to &v[0 it, or you can use &*v.begin (), but it's not easy to understand. For string s, the form is S.c_str ().

If you want to initialize a vector with data from the C API, you can use vector and array memory layout compatibility to first write the data to the vector and then copy the data to the STL container that you expect to write to.

paragraph - article: Use the Swap skill "Out of the excess capacity."

Vector<contestant> (contestants). Swap (contestants);

The expression vector<contestant> (contestants) creates a temporary vector, which is a copy of contestants: This is done by the copy constructor of the vector. However, Vector copy constructors allocate only the required memory for the copied elements, so this temporary vector has no extra capacity. We then swap the data in the temporary vector and the data in the contestants, after which the contestants has the capacity to be removed, the capacity of the original temporary variable, and the capacity of the temporary variable to become the original contestants bloated capacity. At this point, the temporary vector is destructor, freeing up the memory previously occupied by contestants.

The same technique is useful for string:

string S;

...

String (s). Swap (s);

paragraph A article: Avoid using vector<bool> .

As an STL container,,vector<bool> is only two points wrong. First, it is not an STL container; second, it does not store bool. Besides, everything is fine. So it's best not to use it, you can use deque<bool> and Bitset instead. Vector<bool> comes from an ambitious experiment in which proxy objects are often useful in C + + software development. The C + + Standards Committee was very clear about this, so they decided to develop VECTOR<BOOL> to demonstrate that STL supports "containers that access its elements through proxy objects." They say there is an example in the C + + standard, so people have a reference when implementing their own agent-based containers. However, they found it impossible to create an agent-based container, while requiring it to satisfy all the requirements of the STL container. For a variety of reasons, their failed attempts are left in the standard.

paragraph 3 Chapter related Containers

paragraph - : Understanding Equality ( Equality ) and equivalence ( equivalence ) the difference.

Standard associative containers are always in an orderly order, so each container must have a comparison function (default less). The definition of equivalence is determined by the comparison function. Equality must be equivalent, equivalence is not necessarily equal.

paragraph - : Specifies the comparison type for the associated container that contains the pointer.

Whenever you create an associated container that contains pointers, the container will sort by the value of the pointer (that is, the memory address), and in most cases that's not what you want.

paragraph - rule: Always let the comparison function return in the equivalent case false .

Now I'm going to show you a cool phenomenon. Create a set, use less_equal as its comparison type, and then insert 10 into the collection:

Set<int, less_equal<int> > S; S uses "<=" to sort

S.insert (10);

S.insert (10);

For the second insert, the collection checks to see if the following expression is true:

! (10a <= 10b) &&! (10b <= 10a); Check that 10a and 10b are equivalent, and the result is! (TRUE) &&! (true) is False

There are two 10 in the result set.

Technically, the comparison functions that are used to sort the associated containers must define a "strict weak order" (strict weak ordering) for the object they are comparing.

paragraph - : Do not directly modify Set or Multiset the key in.

If you don't care about portability, and you want to change the value of the elements in set or Multiset, and your STL implementation (some STL implementations, such as SET<T>:: Iterator operator* always returns const t& Can not be modified) allow you to do so, please go on. Just be careful not to change the key part of the element, which is the part of the element that can affect the order of the container.

If you value portability, make sure that the elements in set and Multiset cannot be modified. It cannot be modified at least without coercion of type conversions (converting to a reference type const_cast<t&>).

If you want to make the elements in the set, Multiset, map, and Multimap in a way that is always feasible and safe, you can do this in 5 simple steps:

1. Find the elements of the container you want to modify. If you are not sure of the best practice, article 45th describes how to perform an appropriate search to find specific elements.

2. Make a copy of the elements that will be modified. In the case of map and Multimap, remember not to declare the first part of the copy as Const. After all, you want to change it.

3. Modify the copy so that it has the value you expect.

4. Removing the element from the container is usually done through erase (see article 9th).

5. Insert the copy into the container. If the position of the new element may be identical or immediate to the location of the deleted element in the order in which the container is arranged, insert in the form of "hint" (hint) is used to increase the efficiency of the insertion from logarithmic time to constant time. Take the iterator you got from step 1th as a hint.

paragraph A to consider using a sorted Vector replace the associated container.

Standard associative containers are usually implemented as balanced two-fork lookup trees. That is, the applications that it fits first do some inserts, then do a lookup, then maybe insert some elements, then delete some, then do the lookup, and so on. The main features of this series of time are inserts, deletions, and hyper-search blending. Overall, there is no way to predict what the next operation is for the tree.

Many applications use their data structures in ways that are not so confusing. The process of using their data structures can be clearly divided into three phases, summarized as follows:

1. Set the stage. Create a new data structure and insert a large number of elements. At this stage, almost all operations are insert and delete operations. Little or no lookup operation.

2. Find operations. Query the data structure to find specific information. At this stage, almost all operations are lookup operations, with little or no insertions and deletions.

3. Reorganization phase. Changing the content of the data structure may be to delete all current data and insert new data. In behavior, this phase is similar to the 1th phase. When this phase is over, the application is back to phase 2nd.

paragraph - article: When efficiency is critical, please map::operator[] with Map::insert carefully made a choice between.

Suppose we have a widget class that supports the default constructor and constructs and assigns values based on a double value:

Class widget{

Public

Widget ();

Widget (double weight);

widget& operator= (double weight);

...

}

The map's operator[] function is unique. It has nothing to do with vector, deque, and string operator[] functions, and is not related to the built-in operator [] for arrays. Instead, the actual purpose of map::operator[] is to provide the functionality of Add or update. In other words, for the following example:

Map<int, widget> m;

M[1] = 1.50;

Statement m[1] = 1.50 equals

typedef map<int, widget> Intwidgetmap;

Pair<intwidgetmap::iterator, bool> result = M.insert (Intwidgetmap::value_type (1.Widget ())); Create a new map entry with key value 1 and default constructed values

Result.first->second = 1.50;//Call Assignment constructor

We'd better replace the call to operator[] with a direct call to insert:

M.insert (Intwidgetmap::value_type (1,1.50));

The effect here is the same as in the previous code, except that it usually saves three function calls: a temporary Widget object for creating the default construct, one for destructors, and another for the invocation widget's assignment operator.

Please take a look at the update operation when we choose:

M[k] = v; Use operator[] to update the value of K to V

M.insert (Intwidgetmap::value_type (k,v)). First->second = V; Use Insert to update K's value to V

The insert call requires an object of the Intwidgetmap::value_type type, so when we call insert, we must construct and target an object of that type. This pays for a pair constructor and a pair destructor. This, in turn, leads to the construction and destructor of widgets, because Pair<int, widget> itself, contains a widget object. Operator[] does not use the pair object, so it does not construct and destructor pair or widgets.

If you want to update an existing mapping table element, select operator[], and if you want to add a new element, select Insert.

paragraph - Bar: Familiar with non-standard hash containers.

The standard C + + library does not have any hash containers, and everyone thinks this is a pity, but the C + + Standards Committee believes that the work required to incorporate them into the standard will delay the completion of the standard. There is already a decision to include a hash container in the next version of the standard.

paragraph 4 Chapter Iterator

paragraph Num article: iterator takes precedence over const_iterator , reverse_iterator as well as Const_reverse_iterator .

Reduce the chance of mixing different types of iterators and try to replace const_iterator with iterator. From the point of view of Const correctness, it is unfair to give up the use of const_iteraor just to avoid some possible STL implementation defects. However, given the status of specifying the use of iterator in some member functions of the container class, it is not surprising that iterator is more practical than const_iterator. Moreover, from the point of view of practice, it is not always worth getting involved in const_iterator trouble.

paragraph - article: Using Distance and Advance the container's const_iterator converted into iterator .

The following code attempts to cast a const_iterator to iterator:

typedef deque<int> Intdeque; Type definition, simplifying code

typedef intdeque::iterator Iter;

Typedeef Intdeque:;const_iterator Constiter;

Constiter CI; CI is a const_iterator

...

Iter I (CI); Compilation error. No implicit conversion path from const_iterator to iterator

Iter I (const_cast<iter> (CI)); is still a compilation error. Can not be const_iterator

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.