[DotNET] experience STL. NET translated by Zeng Yi

Source: Internet
Author: User
Tags dotnet
Experience STL. NET

[Translation] zengyi820 2004-10-07

To better adapt STL.. NET development, Visual C ++ product group, re-designed STL in Visual C ++ 2005 and named it STL. NET, which is provided from Beta1 products.

In STL. NET Design, STL implementation uses CLI generic and C ++ template mechanisms. C ++ of Version 2005 will be supported by C ++/CLI dynamic programming, which should be the most suitable language for programmers.

Give programmers a variety of choices

A total of three container libraries are available for programmers to operate on CLI types. These three container libraries are built on three types of parameterized models.

Systems: The Collection library for element-type storage is implemented based on the object base class in the CLI type. The following ArrayList implements the IList interface. It represents an array of type objects. In this example, it is used to control elements of the String type. (Version 2 syntax is used here)

Void objectCollection ()

{

Using namespace System: Collections;

ArrayList ^ as = gcnew ArrayList;

As-> Add ("Pooh"); as-> Add ("Piglet ");

As-> Add ("Eeyore"); as-> Add ("Rabbit ");

As-> Sort ();

Console: WriteLine ("ArrayList holds {0} elements :",

As-> Count );

For (int I = 0; I Count; I ++)

Console: WriteLine (as [I]);

Int index = as-> IndexOf ("Pooh ");

If (index! =-1)

{

// A clear downcast is required

String ^ item = safe_cast (As [index]);

As-> RemoveAt (index );

}

As-> Remove ("Rabbit ");

Console: writeline ("/narraylist holds {0} elements :",

As-> count );

Ienumerator ^ is = As-> getenumerator ();

While (is-> movenext ())

Console: writeline (is-> current );

}

Now we have introduced a new container Library Based on the CLI generic mechanism. You can find it in the system: collections: Generic namespace. This is implemented in Visual Studio 2005 beta1 and may change in the final release version. Collection Is a specific generic base class from which users can derive their own specialized container classes. The following example works the same as the preceding example, but uses the new container library,

Void genericcollection ()

{

Using namespace system: collections: Generic;

Collection ^ Cols =

Gcnew Collection ;

Cols-> Add ("Pooh"); cols-> Add ("Piglet ");

Cols-> Add ("Eeyore"); cols-> Add ("Rabbit ");

// No Sort method associated with Collection

Console: WriteLine ("Collection holds {0} elements :",

Cols-> Count );

For (int I = 0; I Count; I ++)

Console: WriteLine (cols [I]);

Int index = cols-> IndexOf ("Pooh ");

If (index! =-1)

{

// Downcast... not required ......

String ^ item = cols [index];

Cols-> RemoveAt (index );

}

Cols-> Remove ("Rabbit ");

Console: WriteLine ("/nCollection holds {0} elements :",

Cols-> Count );

IEnumerator ^ Is = cols-> GetEnumerator ();

While (is-> MoveNext ())

Console: WriteLine (is-> Current );

}

STL. NET provides a type parameterized model that is different from the previous design style. We will discuss it in the next topic. The following is the implementation of the String container.

# Include

# Include

Void stlCollection ()

{

Vector ^ Svec = gcnew vector ;

Svec-> push_back ("Pooh"); svec-> push_back ("Piglet ");

Svec-> push_back ("Eeyore"); svec-> push_back ("Rabbit ");

// Generic algorithm: sort

Sort (svec-> begin (), svec-> end ());

Console: WriteLine ("Collection holds {0} elements :",

Svec-> size ());

For (int I = 0; I size (); I ++)

Console: WriteLine (svec [I]);

// Generic algorithm: find

Vector : Iterator iter =

Find (svec-> begin (), svec-> end (), "Pooh ");

If (iter! = Svec-> end ())

{

// Downcast... not required ......

String ^ item = * iter;

Svec-> erase (iter );

}

// Generic algorithm: remove ......

Remove (svec-> begin (), svec-> end (), "Rabbit ");

Console: WriteLine ("/nCollection holds {0} elements :",

Svec-> size ());

IEnumerator ^ Is = svec-> GetEnumerator ();

While (is-> MoveNext ())

Console: WriteLine (is-> Current );

}

Why STL. NET?

Go deep into STL. before, let's answer an inevitable question briefly: Why should Visual C ++ programmers use STL. NET containers instead of language-neutral systems: Collections or System: Collections: Generic library?

Immediately discard System: The Collections library and Visual Studio 2005 decided to provide generic pants for the same reason: due to the loss of type information, parameterized object models are often complex and insecure. In simple use, for example, if a container contains 16 or fewer elements, it can also be used for Bubble sorting. But when your application involves real-world problems, you must provide a more comprehensive solution.

Therefore, STL. NET and System: Collections: Generic libraries become alternatives for System-level programming languages such as Visual C ++. Why should Visual C ++ programmers prefer STL. NET? Isn't our program isolated from other. NET languages? This is a very practical question and it is worth a reply.

One of the replies is "extensibility )". Originally, STL was designed by Alex Stepanov to store algorithms and containers in different domain spaces. In this way, you can add algorithms applicable to all containers to the algorithm set, or add containers that can be applied to each algorithm to the Container set. Generic libraries are a more traditional model. This leads to our second response.

The second response is "unification )". Programmers who are using C ++ now use this library and the existing code level has reached the expert level. We not only hope to provide a way to migrate existing code, but also hope that the accumulated expert experience of programmers will still be applied. If you rely on STL for C ++ programming, and it is hard to imagine that a C ++ programmer does not depend on STL. NET will make you feel a huge mistake-at least this is my previous experience. Many C ++ experts I have talked with have mentioned this issue and therefore expressed their reserved attitude towards migrating to. NET.

The third response is "performance ". However, C ++ programmers have long been reluctant to mention these clichés about the topic of performance. I have just mentioned it here-it will be discussed in depth in subsequent articles.

The last question is. These are all very good and very good. Stan, but isn't this a gap between C ++ programmers and C ++/CLI programs and other parts of the. NET community? I think the answer to this question is very simple ". STL. NET System Architect, including Anson Tsao, Martyn Lovell, and P. j. plauger has carefully considered this issue. With support for IEnumerator, IList, and ICollection, we provide STL. NET and other. NET language is very confident in the ability to operate together. We will discuss it in depth in subsequent articles.

Define a public foundation

There are two methods to thoroughly understand and use STL. NET: one is to understand the differences between STL and STL. NET. Another way is to understand what they have in common. Although those who have extensive experience with STL seem to need a "list of differences", this does not allow you to escape from unfamiliar libraries. So, when we slow down and dive deep into these or those containers and how they interact with the System collection library, and so on-although they are neat and elegant, but isn't it better for us to understand these new content directly? At least in the brief introduction below, I hope you will do this. By using this method, new users can understand the extended models of parameter sets provided by STL and STL. NET.

So what are the commonalities between STL and STL. NET? Both components include Sequential and associative container types, as well as a generic algorithm set. (Yes. If you are an experienced STL developer, you should know what I will discuss below. The two have the same terminology and background, so you have to be patient .) Generic algorithms do not directly operate on container types. Instead, we use an iterator to pair the elements used for the operation. The element range symbol (the formal term is left inclusive) is as follows:

// Reading: including first, but not last

[First, last)

This indicates that the range starts from first and ends with last, but does not contain last. When first is equal to last, this range is empty.

Sequential containers store sequence sets of independent types of elements. Vector and list are two major sequential containers. (The third sequential container is the deque-pronunciation deck-which provides the same vector function, but is used to efficiently insert and delete the first element. We generally prefer deque instead of vector, for example, the implementation of a queue .)

Before accessing a continuous container type, we must include the appropriate header file, as shown below:

# Include

# Include

# Include

These header files also contain declarations of shared base class interfaces, such as interface_vector and generic applications in containers, such as generic_vector.

The STL. NET container is of the reference type. The Container Declaration contains a tracking handle-it will be automatically initialized to nullptr. We use the gcnew operator to allocate an actual container. As we mentioned in the previous section, I will explain in detail:

Void f ()

{

// Allocate an empty vector )......

Vector ^ Svec = gcnew vector ;

// Allocate a table with 10 elements (list)

// Each value is set to nullptr by default.

List^ Olist = gcnew list(10 );

// The tracking handle value is automatically set to nullptr.

Deque ^ Ideck;

// Do something interesting ......

};

We will discuss the Declaration and usage of sequential containers in subsequent articles in this series.

Associative container supports efficient query of existing elements. Map and set are the two most important types of associated containers. Map is a key/value Pair: key is used for query, and value is used to store and retrieve data. For example, the telephone number book can be expressed simply by map: the key is the name of each person, and the value is the associated phone number.

Map uses the underlined tree abstraction to sort entries in ascending order of values. The hash_map container can perform more efficient retrieval and sorting. Despite this, hash_map iterations also randomly access elements to some extent. If the search is the main activity in map, the hash_map container should be preferred.

Set contains a single key value and supports efficient query of whether an element exists. For example, when creating a text dictionary, the text query system may need to create a common word set and exclude it from the text, such as the, and,. The program will read every word in the text in turn, check whether it refuses to accept the word in the vocabulary, based on the query results, ignore the word, or store it in the database. In addition to set, there is also a hash_set container, which has the same features as map and hash_map.

Map and set can only contain one key ). Multimap and multiset support multiple identical keys. Taking our phone number book as an example, we may need to list a person in multiple tables. In this case, we need to use multimap. Hash_multimap and hash_multiset also exist.

The header files associated with these container types are as follows:

// Used for map and multimap

# Include

// Set and multiset

# Include

// Used for hash_map and hash_multimap

# Include

// Used for hash_set and hash_multiset

# Include

A simple demonstration

Let's discuss it in detail through an instance. The following example implements text vocabulary statistics. It shows the use of map, hash_set, and vector. The function declaration is as follows:

Map ^

Build_word_count (vector ^> ^ words,

Array ^ Common_words)

The template syntax looks very complicated. Let's see what improvements can be made. The returned type of build_word_count () is map, and the key (key) is the value of each word different from other words in the string-text, which is an integer used to count the number of occurrences of correlated words. The first parameter of the function is the CLI array vector, which saves the words in the file as a string element. The 2nd parameters contain the character set to be excluded.

This looks quite complicated because many "hats" are separated from the right brackets. We can use typedef to simplify the text:

Typedef Array ^ Words;

Typedef Vector ^ Text;

The function that is redefined using typedef is as follows:

Map ^

Build_word_count (Text thetext, words common)

We can also remove explicit map declarations, but I still keep them for reader exercises. The next step is implementation. We can divide it into two parts: (1) initialization of MAP and hash_set, as shown below, (2) Actual text processing program.

// Item 3: Initialize the container

// Allocate an empty map ...... We don't know the size of it ......

Map ^ WordOccur = gcnew map ;

// Fill hash_set with elements in the array

Hash_set ^ ComWords =

Gcnew hash_set (

& Common [0],

& Common [common-> length]);

If you are not familiar with STL, the initialization of hash_set may make you feel unfamiliar. However, in addition to syntax, its declaration is very direct and powerful.

What we need to do is to use elements in the array to initialize hash_set. Obviously, we can do this. Of course, we need to use a for each statement for iterative implementation. For example,

// Simplify the hash_set Declaration

// Part 1: Allocate an empty hash_set

Hash_set ^ ComWords = gcnew hash_set ;

// Part 1: Fill hash_set with elements in the array

For each (String ^ wd in common)

ComWords-> insert (wd );

The constructor that loads the address of the first until the last element in the array into hash_set provides the same opportunity for the element to be loaded into hash_set. These two addresses provide an element range for the iteration of the hash_set constructor and insert them into the container in turn. This is the scope of the iterator I mentioned at the beginning.

2nd of the implementation is text processing. Because we have not seen the officially released iterator, we still use the for loop to traverse the vector. We will use the for each statement to traverse every array element of the vector. This is the code described above:

// Cyclically access each array

For (int ix = 0; ix size (); ++ ix)

{

For each (String ^ wd in theText [ix])

If (common-> find (wd) = common-> end ())

Word_map [wd] ++;

}

// Do not forget to return results ......

Return word_map;

Find () is a member function of hash_set. It is used to determine whether a word item already exists in the set.-All associated containers support the find () member function. (Yes, sequential containers, built-in arrays, and all collections that you may integrate into the STL/STL. NET model make the find () Generic algorithm. Theoretically, the isolation between algorithms and containers is more serious than that of containers. We will particularly discuss the list sequential container ).) The returned result is an iterator in the container that I have not discussed. In this case, we assume that the iterator is of the pointer type. If a word item already exists in the container, find () returns an iterator to it. Otherwise, the iterator of the last word item is returned. This is the same as the iterator value returned by end. The method for determining whether the element search in STL is successful is to compare whether the iterator value returned by the search method is the same as the iterator value returned by the end () method. If the two are the same, the elements are not in the container.

Each container provides the begin () and end () member functions. Begin () returns an iterator for the first element in the container. As I mentioned earlier, end () returns an iterator for the last element in the container. For example, the following program shows how to declare two iterators and use these two member functions to initialize them,

Vector : Iterator first = theText-> begin ();

Vector : Iterator last = theText-> end ();

Container traversal generally increases first in a for loop or while loop, and terminates the loop when first equals last. For example,

For (; first! = Last; ++ first)

The requirement of the iterator is that they must be able to use the incremental operator to repeat applications that start with "first" and reach "last. However, the compiler itself cannot do this; otherwise, undefined run-time behavior will be generated ).

We use the anti-reference (*) operator to access the elements involved in the iterator. For example, to obtain every CLI array element of our vector, we write the following code in the for loop body,

Array ^ As = * first;

We will introduce the Declaration and usage of associated containers in subsequent articles of this series.

Algorithm selection

Generic algorithms provide operations for these container types and two built-in array elements. These operations include Search (find, count), Sort (merge, partition, permutate, reverse, rotate, shuffle, sort), Deletion/Subtitution (remove, replace, swap, unique ), copy, Relational (equal, min, max, includes), Generate (fill, for-each, generate, transform), Set (union, intersection, difference), Heap (make, sort, pop, push), and many profound digital operations, such as integral, partial summation, inner product, and adjacent difference ).

Before using generic algorithms, we must include the corresponding header files. All other algorithms except the numeric algorithm are written as follows:

# Include

The four numeric algorithms, integral, partial summation, inner product, and adjacent are separated into a separate header file. When using these algorithms, we write the header file as follows:

# Include

(I have been looking for reasons why the header files for these four operations have been put forward separately-This obviously complicate the discussion of the use of algorithms-but whether in the document or after in-depth research, I still cannot find the answer. In the original Stepanov implementation, these four operations use the same header file as other algorithms. During the standardization process, the numeric header file was introduced and discussed in the standard election part of the font library .)

You might think, oh, Stan, these should not be written. ? After all, this is the method for verifying the container header file. Isn't that self-defeating? Surprisingly, the answer is "no ". I'm surprised because STL and STL. NET adopt the same implementation method. God, we have discussed code reuse!

Okay. Let's see how to use these algorithms. For example, let's sort string element arrays before inserting them into map. We will use sort () Generic algorithm to implement it. For all generic algorithms, parameters are almost the scope of the iterator pair:

Sort (& as [0], & as [as-> length]);

The other two generic algorithms-find () and remove () are also used in the initial code ():

// Generic algorithm: Find

Vector : Iterator iter =

Find (SVEC-> begin (), SVEC-> end (), "Pooh ");

If (ITER! = SVEC-> end ()){...}

// Generic algorithm: remove ......

Remove (SVEC-> begin (), SVEC-> end (), "rabbit ");

So far, we should be very sensitive to the usage patterns here: the range divided by the iterator is inseparable from the container algorithm. The search algorithm returns an iterator, which is used to discover items in the container or cannot be found. The iterator is used to identify the last item in the range.

We will use generic algorithms to do something interesting-but this must be done in subsequent articles. I hope this will give us a good overview of what we will discuss and provide a public vocabulary and background knowledge for us to move forward as a learning group. Next time.

Thanks

Even the simplest articles are published, there are many hands behind the dual platforms to help. I would like to solemnly thank Scott Currie for his profound comments in the final document. I already think there is no room for modification! Anson Tsao has given me a lot of guidance on STL. NET. I would like to express my sincere thanks for this. Martyn Lovell is in control of the STL. NET deployment progress. Thanks to him for allowing me to track STL. NET development along the way. Finally, I would like to thank Brian Johnson and Ronald Laeremans for making me confident in writing this series of articles.

Trackback: http://tb.blog.csdn.net/TrackBack.aspx? PostId = 128887

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.