The misunderstood C ++ -- sharpen the knife without mistake

Source: Internet
Author: User

Sharpen the knife without mistake
The old saying "don't cut firewood by mistake" is not suitable for C ++. If C ++ is compared to a knife, it will be a knife with excellent materials and shapes-just without a front. So we need to "Sharpen the knife ".
C ++ this knife material is hard, the strength is also high, may also be processed over the surface. It is naturally difficult to grind, time-consuming and labor-consuming. However, once it is ground, it will be sharp and durable. This is worth it.
The "sharpening" of C ++ is actually a development library, a variety of possible libraries, starting from the basic library, to various application libraries. The more databases, the faster the knife is. Of course, there is a price for the development library. It takes time, effort, and patience.
At this time, we need to make some estimation and four arithmetic operations to choose how to sharpen the knife.
The most critical factor is the number of times a job is repeated, or the number of jobs that are similar. The number of repetitions of a job clearly indicates that it is silly to repeat what you have already done. "Copy-paste magic power" uses the source code's reproducibility to easily avoid repeated encoding. However, this is just a little "not so stupid.
When these repeated code changes, each paste place needs to be modified or replaced. As a result, smart people have invented various technical means such as subroutines, functions, classes, inheritance, polymorphism, templates, etc. The purpose is to eliminate this "stupid" or "not so stupid" approach. Once a job is made into a subroutine, function, class, template, etc., a library is actually formed, but the application scope of the library is different.
In contrast, similar jobs have a much more complex and ambiguous meaning. When coding, we often find that some jobs have different degrees of similarity. For example, we write a sorting algorithm for the int type. Next time we write the same Sorting Algorithm for the double type ;.... The number of times the algorithm is written for the sort type. These algorithms are not exactly the same (different types), but have the same structure. Therefore, we can use a generic algorithm to sort all types of data (not considering performance issues and type concept requirements ).
Of course, not all codes have such high similarity. The less similarity the Code has, the more difficult it is to create abstract library code. Therefore, there are limits to the database. Taking into account the cost and utility of creating a database, you can guide us to establish a database or how to create a database.
For exactly the same code, you don't have to say, just make it into the library code. This is because the workload of the library code is only a little more than the workload of writing the code once. The same is true for modifications.
For similar code, the situation is much more complicated. Generally, if there are only a small number of similar codes, such as 3 and 4, there is usually no need to create the corresponding library code. Especially when the similarity between these similar codes is small, or the code is complex. At this time, the cost of creating a database is very high, but the benefits are only 3 and 4.
However, it must be noted that when considering whether to create a database, we must also carefully consider other projects or the possibility of application in future projects. If it is a very common function, although it only appears once in the current project, considering the application of other projects in the future, it should also be developed into a library.
Back to the metaphor of cutting firewood. A knife without opening a tree can cut some branches to a certain extent, but it is difficult to cut and cannot cut down coarse branches. If I only need to cut a few branches, I don't need a lot, and I won't cut firewood any more in the future. A blunt knife is enough. In this case, it is a waste of effort to sharpen the knife. On the contrary, if I want to cut a whole load of firewood today, or I need to cut firewood day after day. So I 'd better sharpen the knife.
Sharpening is also difficult. Hard Material (commonly known as "Steel fire" Good) knife, grinding effort. But it is more sharp and durable. The tool with a soft material can be quickly ground up. However, it is difficult to make it competitive and durable. (Because of the soft material of the knife, after grinding to a certain extent, the edge will roll up. If it is worn in turn, it will be rolled back ).
C ++ is the kind of hard knife. (And the manufacturer did not charge for the cost ). Therefore, as a professional hacker, it is necessary to sharpen this knife. (Of course, there are also many "professional cheaters" who are easy to grind, or who are already working at the factory ").
Sharpening is also exquisite. (Haha, I think there are still one or two hands in sharpening. & #61514 ;). The harder the knife is, the less urgent it is. In order not to delay the production of firewood, only one point can be ground and one point can be used. First, use a large angle to sharpen the fast port on the front port. Although the front-ends of a large angle are not as sharp as those of a small angle, they are better than those without a front-ends. More importantly, it takes much less time for a large-angle front port than a small one. Because I have a good knife in my hand, there is basically no loss in the process of cutting firewood. The next day, I will sharpen my knife at a small angle. Similarly, I don't plan to deal with it all in the next day. I continue to cut firewood with a half-worn knife. After the second day of sharpening, the knife will be easier to use than the first day. Then the third day is the same as the second day. And so on, until a few days later, the knife was completely ground. After that, you only need to regularly polish the tool to maintain its sharpness. In contrast, soft knives need to be worn more frequently to maintain sharpness.
All right, just sharpen it here. Let's take a look at how to "Grind" C ++. Here we will use a real case to illustrate it.
Nowadays, many application software, especially MIS software, need to access the database, extract the data, perform further processing, or directly display it on the interface. The following code must be everywhere in the software:
Void onqueryclicked ()
{
Dataconnection DC _(...);
Rowset Rs _ (DC _, "select... From ...");
Int J (0 );

M_resgrid.clear ();
M_resgrid.setcolnumber (RS _. colnumber ());

While (RS _. movenect ())
{
For (INT I = 0; I <Rs _. colnumber (); ++ I)
{
M_resgrid.addrow ();
M_resgrid.cells (J, I) = Rs _. Field (I );
}
++ J;
}
}
Common Code. M_resgrid is a grid control on the interface. It is also assumed that Rs _ has been bound with a string and can directly output a string.
Now let's use our imagination. What if the RS _ and grid control m_resgrid of the result set both support interfaces of the standard STL container? We can rewrite the above Code in the following ways:
Void onqueryclicked ()
{
Dataconnection DC _(...);
Rowset Rs _ (DC _, "select... From ...");
Int J (0 );

M_resgrid.clear ();
M_resgrid.setcolnumber (RS _. colnumber ());

STD: Transform (RS _. Begin (), RS _. End (), STD: back_inserter (m_resgrid), copyrstogrid ());
}
It's much simpler, isn't it? But there is a problem. This transform only replaces the original outer loop, that is, the while (). The memory loop, that is, the loop on the column of RS _, has not been done yet.
The solution is not complex, that is, the role of copyrstogrid: a function or function object that executes an internal loop:
Struct copyrstogrid
{
Grid: Row operator () (rowset: Row const & Row ){
Grid: Row gridrow _ (row. fieldnum ());
STD: Copy (RS _. Begin (), RS _. End (), gridrow _. Begin ());
Return gridrow _;
}
};
After writing this function object, you can use it all the time without having to write it again. Therefore, we can use a line of code to replace the original two loops/five lines of code (not curly braces ). This benefit may not seem too big, but considering the large number of result sets in the software to copy the data of the display control, this difference has accumulated considerable.
Another problem is performance. STD: Transform () has no major performance issues. The problem lies in copyrstogrid. According to STD: Transform (), operator () returns grid: Row and a value. Returning non-trivial values is notorious for performance. Modern compilers usually execute nrv optimization, and simple function objects such as copyrstogrid can be guaranteed. Even if nrv optimization is not possible, a more direct optimization solution is provided below. In the future, the right-value reference of C ++ 09 can be used to completely eliminate such performance risks.
After the STL of the result set and grid controls, the benefits are not only data replication, but also data filtering, deletion, conversion, query, and sorting, it will lead to a lot of simplification. After a long period of development, we have become accustomed to loop, manual data copying, conversion, and query. Many times, we write some implicit algorithms again and again. I often see that someone uses a naked loop to search for a specific data on a grid. (These also include myself ). More than once, I have searched for a widget, container, or class in the document to see if there is a member function named "find" or "Search. In contrast, it is cool to query data directly using an algorithm with unique semantics such as find or find_if without considering the data type.
The next question is: how to make the result set, interface controls, and other containers STL. This will return to the topic of this article-sharpening. That is, the database. We can develop a fully STL-based database access library based on ODBC or oledb. However, it is not very cost-effective to become a mentor. Yes, it is necessary to sharpen a knife, but we are not stupid enough to sharpen a steel ingot into a firewood knife. You can start from the billet that has been forged.
Many existing database access libraries provide well-developed database access components. We can use these ready-made libraries to STL them based on them. The specific method is to make an adapter. In fact, all the result set components provided by the data access library have the most basic characteristics of a container. But its interface does not comply with STL standards. Therefore, we only need to add an intermediate layer to convert all related interfaces into STL forms:
Class stl_rowset
{
Public:
Stl_rowset (crecordset const & RS): m_rs (RS ){}
...
Iterator begin ();
Iterator end ();
Void push_back ();
Void insert ();
...
PRIVATE:
Crecordset & m_rs;
};
With this adapter, we can "Dress Up" a result set as an STL container. Therefore, the standard algorithms of STL can be directly used. The key here is the iterator. Making an iterator is a tough task. Boost: iterator helps us quickly and conveniently build an iterator.
The iterator also brings us an additional benefit. For the forward_only cursor, you can use the forward iterator. For other scrollable types, you can use the Radom iterator. As a result, when I plan to perform a reverse operation on the result set of a forward_only cursor, The iterator can block me during compilation so that I can block this error as soon as possible.
Similarly, you can create an adapter for interface controls or any other component similar to a container. As a matter of fact, someone has already done this. The stlsoft series library developed by Matthew Wilson provides adapters for different platform systems, allowing us to easily use standard algorithms for interfaces or other components.
Furthermore, we can create some generic adapters so that some components with common interfaces can share an adapter without repeated efforts. I have made some attempts in a previous post "powerful C ++ -- a thousand people side" (http://community.csdn.net/Expert/TopicView3.asp? Id = 5504301 ). It is still troublesome in the existing C ++. In the future, with the support of C ++ 09 concept and concept-map, this type of generic adapter will be easily implemented.
Now let's look back and look at the performance problems mentioned above. Because we have created an adapter, and the adapter is made by ourselves. Therefore, we can do something on the value_type of the adapter. STL specifies that each container must have a typedef... Value_type ;. This type is the iterator value type. We can define this type as follows:
Class stl_grid
{
Class stl_row
{
Template <typename T> stl_row (T const & V ){
Copy_row (v, * This );
}
Template <typename T> stl_row & operator = (T const & V ){
Copy_row (v, * This );
}
Typedef stl_row value_type;
...
}
...
};
Copy_row is an auxiliary function template used to copy different types of rows:
Template <typename from, typename to>
Void copy_row (from const & from, to & ){
STD: Copy (from. Begin (), from. End (), to. Begin ());
}
In this way, you can use STD: copy instead of STD: Transform to copy data, which is more direct and efficient:
Void onqueryclicked ()
{
Dataconnection DC _(...);
Rowset Rs _ (DC _, "select... From ...");
Int J (0 );

M_resgrid.clear ();
M_resgrid.setcolnumber (RS _. colnumber ());

Stl_rowset (RS _) stlrs _;
Stl_grid (m_resgrid) stlgrid _;

STD: Copy (stlrs _. Begin (), stlrs _. End (), STD: back_inserter (stlgrid _));
}
If you have special requirements, you can reload or make the copy_row special. If you need to implement local features, you can make copy_row a function object.
Based on these adapters, you can also derive a variety of complex uses and algorithms. For example, you can create a column adapter for the result set to strip a column from the result set. A group of column adapters can be used to strip a group of columns and then perform various arithmetic and logical operations, or even matrix operations, on this group of columns. If necessary, you can also use a template expression to optimize the computing performance.
This is not widely used. But in general, we can spend some extra time and effort in the software development process to develop some useful libraries. These libraries will bring us a lot of benefits in the current project or future projects. However, as with other things in the world, the efficiency of software development through development libraries is also subject to the 2-8 principle. 80% of results come from 20% of efforts. That is to say, when we achieve the key 20% of the work, we will get a lot of benefits, while the rest of the work will only bring us a 20% improvement in efficiency. Therefore, the development library should start from some key points, such as the STL adapter, without the need to fully develop a database access or GUI library. In this way, we will get the greatest benefit. Although developing a complete, comprehensive, and perfect GUI looks so glorious, brilliant, and glorious, it is not the most economical method from a realistic perspective, it is not the best way for ordinary programmers who are busy making money to support their families. Especially in C ++, a rather difficult language.
Okay, that's all. Have the opportunity to sharpen your knife.

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.