Reduce the Compilation Time of C ++ code.

Source: Internet
Author: User

Reduce the Compilation Time of C ++ code.

The c ++ code consists of the header file and the implementation file. The header file is generally provided for use by others (also called customers). However, once the header file changes, no matter how small the changes are, all files that reference them must be re-compiled, and it takes time to compile them. If the project you are doing is large (such as secondary development of chrome ), re-compilation will waste most of the work time. It takes a very long time to recompile it, but your boss said that you didn't produce it, and you were fired. Isn't it so bad, if you see this article earlier, you will be more efficient than your colleagues in development, so fired will not be yours. Do you say this article is worth a thousand RMB! Joke :)

Let's get down to the truth and introduce the Compilation Time. I know three methods:

1. Delete unnecessary # include. The alternative method is to use forward Declaration (forward declared)

2. Delete unnecessary private member variables and use the "impl" method.

3. Delete inheritance between unnecessary classes

 

In order to clarify these three points, it is better to give an instance. I will improve this instance step by step (because I also found it out at 1.1 points. If something wrong, you can rest assured, I will argue with you to the end, haha)

Now let's assume that you find a new job and take over the classes written by a previous programmer, as shown below:

// Old. h: This is the class you receive. // # include <iostream> # include <ostream> # include <list>/5 are file, db, cx, deduce or error, level Limited, no template class // only use file and cx to have virtual functions. # include "file. h "// class file # include" db. h "// class db # include" cx. h "// class cx # include" deduce. h "// class deduce # include" error. h "// class error class old: public file, private db {public: old (const cx &); db get_db (int, char *); cx get_cx (int, cx); cx & fun1 (db); error fun2 (error); virtual std: ostream & print (std: ostream &) const; private: std :: list <cx> cx_list _; deduce deduce_d _;}; inline std: ostream & operator <(std: ostream & OS, const old & old_val) {return old_val.print (OS );}

  

After reading this class, if you already see where the problem is, you don't need to read it next. You are a master. These basic knowledge is too child care for you, if you have been stunned during the interview, take a look.

First, let's see how to use Article 1: Delete unnecessary # include

This class references five header files, which means that the header files referenced by the five header files are also referenced. In fact, you do not need to reference five header files. You only need to reference two header files.

1. Delete unnecessary # include. The alternative method is to use forward Declaration (forward declared)

1.1 Delete the header file iostream. When I first started to learn c ++, I copied it according to "c ++ primer". As long as I saw the input, I added the iostream header file to the output file. Several years have passed, now I know this is not the case. Here we just define the output function, as long as we reference ostream.

1.2.do not use ostream header files. replace them with iosfwd. The reason is that parameters and return types can be compiled as long as they are declared in the forward direction. In the iosfwd file, there are 678 lines (my environment is vs2013, different compiling environments may have different locations, but all of them have this statement .)

Typedef basic_ostream <char, char_traits <char> ostream;

Inline std: ostream & operator <(std: ostream & OS, const old & old_val)

{Return old_val.print (OS );}

In addition, if you say that this function is required to operate the ostream object, you still need to # include <ostream>. You are only half right. Indeed, this function needs to operate the ostream object, but please refer to his function implementation,

There is no such statement defined in it as std: ostream OS. In other words, when such a definition statement appears, you must # include the corresponding header file, because this is to request the compiler to allocate space, and if only class XXX is declared in the forward direction, how does the compiler know how much space is allocated to this object!

 

Here, the header file of old. h can be updated as follows:

 

// Old. h: This is the class you receive // # include <iosfwd> // The new header file # include <list> // five are file, db, cx, deduce or error, level Limited, no template class // only use file and cx to have virtual functions. # include "file. h "// class file, which cannot be deleted as the base class. The Compiler does not know how much space is allocated when the old object is instantiated. # include" db. h "// class db, which cannot be deleted as the base class. Same as # include" cx. h "// class cx # include" deduce. h "// class deduce // error is only used as the parameter and return value type, replaced with the Forward Declaration # include" error. h "class error; class old: public file, private db {public: old (const cx &); db get_db (int, char *); cx get_cx (int, cx ); cx & fun1 (db); error fun2 (error); virtual std: ostream & print (std: ostream &) const; private: std :: list <cx> cx_list _; // cx is a template type, neither a function parameter type nor a function return value type, so cx. the h header file cannot delete deduce deduce_d _; // deduce is a type definition and does not delete its header file}; inline std: ostream & operator <(std: ostream & OS, const old & old_val) {return old_val.print (OS );}

 

  

So far, I have deleted some code. Is it a good mood? It is said that it depends on how high a programmer is, not how much code he has written, but how much less code he has written.

If you are more interested in C ++ programming, you will continue to read the following text and delete the code. But this time you will find another way.

 

2. Delete unnecessary private member variables and use the "impl" method.

. Use the "impl" Implementation Method to write code to reduce the compilation dependency of client code

The impl method is to put all the private member variables of the class into an impl class, and then keep only one impl * pointer for the private member variables of the class. The Code is as follows:

 

// File old. h class old {// public and protected members private: // private members, as long as any header file changes or the number of members increases, all references old. h client must be re-compiled // private members; whenever these change, // all client code must be recompiled };

 

  

Rewrite it as follows:

// File old. h class old {// public and protected members private: class oldImpl * pimpl _; // replace all original private member variables with the impl pointer, the pointer can be compiled only by the Forward Declaration. This method puts forward declaration and definition pointer together. // Of course, you can also separate the write // a pointer to a forward-declared class}; // file old. cpp struct oldImpl {// The true member variables are hidden here. The client code does not need to be re-compiled. // private members; fully hidden, can be // changed at will without recompiling clients };

  

I don't know if you understand it. If you don't understand it, please write a class test. I did this. Of course, everything also has advantages and disadvantages. The following is a simple comparison:

 

 

 

Use impl implementation class

Do not use impl implementation class

Advantages

The type definition is isolated from the client, reducing # include times, improving Compilation speed, modifying library classes at will, and the client does not need to re-compile

Direct, simple, and clear. You do not need to consider heap allocation, release, and memory leakage issues.

Disadvantages

For impl pointers, heap allocation and heap release are required. After a long time, memory fragments are generated, which affects the program running speed. Every time a member function is called, impl-> xxx () one-time forwarding

Any header file on the library has changed and the client must be re-compiled.

 

After impl is implemented:

// Only use file and cx to have virtual functions. # include "file. h "# include" db. h "class cx; class error; class old: public file, private db {public: old (const cx &); db get_db (int, char *); cx get_cx (int, cx); cx & fun1 (db); error fun2 (error); virtual std: ostream & print (std: ostream &) const; private: class oldimpl * pimpl; // Forward Declaration and definition}; inline std: ostream & operator <(std: ostream & OS, const old & old_val) {return old_val.print (OS );} // implementation file old. cppclass oldimpl {std: list <cx> cx_list _; deduce dudece_d _;};

  

3. Delete inheritance between unnecessary classes

Object-oriented provides the inheritance mechanism, but the inheritance should not be abused. the inheritance of old class is one of abuse. class old inherits the file and db classes, and the inheritance of file is the public inheritance, inheriting databases is private inheritance

The inheritance of file can be understood, because there are virtual functions in the file, and old needs to be redefined, but according to our assumptions, only file and cx have virtual functions. How can we explain the private inheritance of db ?! The only possible reason is:

Using private inheritance-a class cannot be used as a base class to derive other classes. Similar to the final keyword function in Java, this is obviously not the purpose of the instance, therefore, this private inheritance is completely unnecessary. Instead, you should use the functions provided by the db class in the include mode, so that you can

Delete the "db. h" header file and put the db instance into the impl class. The final class is as follows:

 

// Only use file and cx to have virtual functions. # include "file. h "class cx; class error; class db; class old: public file {public: old (const cx &); db get_db (int, char *); cx get_cx (int, cx); cx & fun1 (db); error fun2 (error); virtual std: ostream & print (std: ostream &) const; private: class oldimpl * pimpl; // Forward Declaration and definition}; inline std: ostream & operator <(std: ostream & OS, const old & old_val) {return old_val.print (OS );} // implementation file old. cppclass oldimpl {std: list <cx> cx_list _; deduce dudece_d _;};

 

  

Summary:

This article briefly introduces several methods to reduce Compilation Time:

1. Delete unnecessary # include. The alternative method is to use forward Declaration (forward declared)

2. Delete unnecessary private member variables and use the "impl" method.

3. Delete inheritance between unnecessary classes

 

These articles may be helpful to you. If I have not made it clear, you can refer to the attachment and complete examples. You are also welcome to comment on them and discuss the progress together, oh no, raise your salary. In the next article, I will analyze the impl implementation method in detail. Let's look forward to it...

 

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.