Path to Qt Learning (36): traversal and implicit data sharing of Qt containers

Source: Internet
Author: User

As mentioned above, the Qt container class provides two traversal devices: Java and STL. The former is relatively easy to use, while the latter can be used in some algorithms with powerful functions. For each container class, there is a corresponding traversal: Read-only traversal and read/write traversal. The read-only traversal tool has three types: QVectorIterator <T>, qinilistiterator <T>, and QListIterator <T>. The read/write traversal tool also has three types, but the name has a Mutable, QMutableVectorIterator <T>, QMutableLinkedListIterator <T>, and QMutableListIterator <T>. Here we only discuss the QList traversal tool, and the rest of the traversal tools have almost the same API. Shows the location of the Java-style traversal tool (from C ++ GUI Programming with Qt4, 2nd Edition): 650) this. width = 650; "onclick = 'window. open ("http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'border = "0" alt = "" src = "http://www.bkjia.com/uploads/allimg/131228/1R33A514-0.png"/> we can see that the Java-style traversal tool does not point to any element, it points to the position before the first element, between two elements, or after the last element. The typical code for Traversing with a Java-style traversal is: 650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> QList <double> list;
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> //...
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> QListIterator <double> I (list );
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> while (I. hasNext ()){
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> doSomethingWith (I. next ());
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align = "top" src = "http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif"/>} by default, this traversal tool points to the first element and uses the hasNext () and next () functions to traverse from front to back. You can also use the toBack () function to point the traversal to the position next to the last element, and then use the hasPrevious () and previous () functions to traverse. This is a read-only traversal, And the read/write traversal can add, delete, and modify operations during traversal, for example: 650) this. width = 650; "onclick = 'window. open ("http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> QMutableListIterator <double> I (list );
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> while (I. hasNext ()){
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> if (I. next () <0.0)
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> I. remove ();
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align = "top" src = "http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif"/>} Of course, the reader can also traverse from the back to the front, the specific API and the previous almost the same, I will not go into details here. Corresponds to a Java-style traversal device. Each sequential container Class C <T> has two STL-style traversal devices: C <T >:: iterator and C <T >:: const_iterator. As the name implies, const_iterator does not allow us to modify the traversal data. The begin () function returns the STL-style traversal tool pointing to the first element, for example, list [0], while the end () function returnsElements after the last oneFor example, if the length of a list is 5, The traversal tool points to list [5]. The valid position of the STL style traversal tool shown: 650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'border = "0" alt = "" src = "http://www.bkjia.com/uploads/allimg/131228/1R33A424-12.png"/> If the container is empty, begin () and end () are the same. This is also one of the methods used to check whether the container is empty, but it is more convenient to call the isEmpty () function. The syntax of the STL-style traversal tool is similar to the operation of Arrays Using pointers. We can use the ++ and -- operators to move the traversal tool to the next position. The returned value of the traversal tool is a pointer to this element. For example, the iterator returned by QVector <T> is of the T * type, while the const_iterator returned is of the const T * type. The code for a typical STL-style traversal is: 650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> QList <double >:: iterator I = list. begin ();
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> while (I! = List. end ()){
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> * I = qAbs (* I );
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> + + I;
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align = "top" src = "http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif"/>} for some functions that return the container, if you need to use an STL-style traversal, we need to create a copy of the returned value and then use the traversal tool to traverse it. As shown in the following code: 650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> QList <int> list = splitter-> sizes ();
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> QList <int>: const_iterator I = list. begin ();
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> while (I! = List. end ()){
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> doSomething (* I );
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> + + I;
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align = "top" src = "http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif"/>} and if you use the return value directly, like the code below: 650) this. width = 650; "onclick = 'window. open ("http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> // WRONG
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align = "top" src = "http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif"/> QList <int>: const_iterator I = splitter-> sizes (). begin ();
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> while (I! = Splitter-> sizes (). end ()){
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> doSomething (* I );
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> + + I;
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/>} is generally not what you expect. Because the sizes () function will return a temporary object, when the function returns, this temporary object will be destroyed, so it is unwise to call the begin () function of the temporary object. In addition, this writing method also has performance problems, because every cycle of Qt needs to re-create a temporary object. Therefore, note that,If you want to use an STL-style traversal tool and traverse the containers that return values, you must first create a copy of the returned values and then traverse them.We do not need to do this when using a Java-style read-only traversal, so the system will automatically create this copy for us. Therefore, we only need to write the following code very easily: 650) this. width = 650; "onclick = 'window. open ("http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> QListIterator <int> I (splitter-> sizes ());
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> while (I. hasNext ()){
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> doSomething (I. next ());
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/>} Here we propose to create a copy of the container, which seems to be a very expensive operation. Actually, this is not the case. Do you remember the previous section about Implicit data sharing? Qt uses this technology to make copying a Qt container class and copying a pointer so fast. If we only perform read operations, the data will not be copied. Only when the data to be copied needs to be written will the data be actually copied, because of this, implicit data sharing is also called "Copy at write time ". Implicit data sharing does not require any additional operations. It is automatically performed. Implicit data sharing gives us a programming style that can easily return values: 650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> QVector <double> sineTable ()
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> {
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> QVector <double> vect (360 );
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> for (int I = 0; I <360; ++ I)
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> vect [I] = std: sin (I/(2 * M_PI ));
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> return vect;
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/>}
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> // call
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align = "top" src = "http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif"/> QVector <double> v = sineTable (); we often write this in Java, which is also natural: create an object in the function and return it after the operation is completed. But in C ++, many people will say that this should be avoided, because the last return statement will copy the temporary object. If this object is large, this operation will be expensive. Therefore, Senior C ++ masters will have a STL style Writing: 650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'ign =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> void sineTable (std: vector <double> & vect)
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> {
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> vect. resize (360 );
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> for (int I = 0; I <360; ++ I)
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> vect [I] = std: sin (I/(2 * M_PI ));
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/>}
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> // call
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> QVector <double> v;
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> sineTable (v); this syntax avoids copying by passing in a reference. However, this writing method is not so natural. The use of implicit data sharing allows us to write data in the first way without worrying about performance issues. All Qt container classes and other classes use the implicit data sharing technology. These classes include QByteArray, QBrush, QFont, QImage, QPixmap, and QString. This makes it highly efficient to use the value transfer method in parameters and return values of these classes. However, to correctly use implicit data sharing, we need to establish a good programming habit. One of these is,Read-only access to the list or vector using the at () function instead of the [] Operator. The reason is that the [] operator can be both the left value and the right value, which makes it difficult for the Qt container to determine whether it is the left value or the right value, and () A function cannot be used as the left value. Therefore, implicit data sharing can be performed. In addition, for begin (), end () and some other non-const containers, Qt performs deep replication when data changes. To avoid this,Use const_iterator, constBegin (), and constEnd () whenever possible ().Finally, Qt provides a method to traverse without the traversal tool: foreach loop. This is actually a macro, using the code as follows: 650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> q1_list <Movie> list;
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> Movie movie;
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/>...
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> foreach (movie, list ){
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> if (movie. title () =" Citizen Kane "){
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> std: cout <" Found Citizen Kane "<std: endl;
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/> break;
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/>}
650) this. width = 650; "onclick = 'window. open (" http://blog.51cto.com/viewpic.php? Refimg = "+ this. src) 'align =" top "src =" http://www.bkjia.com/uploads/allimg/131228/1R33B2c-1.gif "/>} many languages, especially dynamic languages, and after Java 1.5, all have foreach support. In Qt, a macro is used to implement a foreach loop. There are two parameters. The first is a single object and becomes a traversal object, which is equivalent to a pointer to the element type of the container, and the second is a container class. It clearly means that each time an element in the container is retrieved, it is assigned to the previous traversal element for operation. Note that,Define traversal elements outside the loop. For classes with commas in the definition, such as QPair <int, double> is the only choice..

This article is from the "bean space" blog, please be sure to keep this source http://devbean.blog.51cto.com/448512/247353

Related Article

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.