Reprint news methods to reduce C++ code compilation time

The code of c++ consists of header files and implementation files. The header files are generally provided to others (also called customers) for use, but once the header files are changed, no matter how small the changes, all the files that reference him must be recompiled. Compilation will take time. If your project is relatively large (such as the development of secondary packaging of chrome), recompiling once will waste most of the time at work, which is very tiring after a day of work, but your The boss said that you didn't produce any output, and you were fired. Are you complaining? If you read this article earlier, you would be more productive than your colleagues, and it would not be you who were fired. You say this article is worth a thousand dollars!

Closer to home, how to reduce the compilation time, I know only 3 ways:

1. Delete unnecessary #include, the alternative is to use forward declaration (forward declared)

2. Delete a lot of unnecessary private member variables, instead Use the "impl" method

3. Delete unnecessary inheritance between classes

In order to clarify these three points, it is better to give an example. I will improve this example step by step (because I also figured it out bit by bit, If you say something wrong, feel free to spray it, I will argue with you to the end, hehe)

Now let's say you find a new job and take over a class written by a previous programmer, as follows:
C++ code
// old .h: This is the class you receive 
// 
​​#include <iostream> 
#include <ostream> 
#include <list> 
  
// 5 are file , db, cx, deduce or error , limited level no template class 
// only There are virtual functions with file and cx. 
#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 have already seen where the problem lies, you don't need to read the next one. You are a master. These basic knowledge are too childish for you. Let's

see how to use the first item: Delete unnecessary #include

This class refers to 5 header files, which means that the header files referenced by those 5 header files are also referenced. In fact, there is no need to refer to 5 1. Delete unnecessary #include, and the alternative is to use

forward declaration (forward declared)

1.1 Delete the header file iostream. When you see about input and output, add the iostream header file. A few years have passed. Now I know that this is not the case. Here is just to define the output function. It is enough to refer to the ostream. 1.2. The ostream

header file is not needed. , The reason is that the parameters and return types can be compiled as long as they are forwarded. In the iosfwd file, line 678 (my environment is vs2013, the specific location of different compilation environments may be different, but there is this statement) There is this A
C++ code
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 needs to operate on ostream objects, you still need to #include <ostream> , you are only half right, indeed, this function needs to operate on ostream objects, but please see his function implementation,

there is no Define a statement like std::ostream os, then again, whenever such a definition statement appears, you must #include the corresponding header file, because this is a request for the compiler to allocate space, and if you only forward declare class XXX ; How does the compiler know how much space to allocate to this object!

Seeing this, the old.h header file can be updated as follows:
C++ code
// old.h: This is the class you received 
// 
#include <iosfwd> //Newly replaced header file 
#include <list> 
  
// 5 They are file , db, cx, deduce or error. There is no template class for limited level. 
// Only file and cx have virtual functions. 
#include "file.h" // class file, which cannot be deleted as a base class, 
                   // delete The compiler does not know how much space is allocated when instantiating the old object  #include "db.h
" // class db, as the base class cannot be deleted, same as above 
#include "cx.h" // class cx 
#include "deduce .h" // class deduce 

// error is only used as parameter and return type, replace #include "error.h" class error   with forward declaration   ;
  
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, not a function parameter type 
                          // nor a function return value type, so the cx.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 codes, and I am in a good mood. It is said that to see how high a programmer is, it is not how much code he has written, but how much code he has written less.

If you have a deeper interest in C++ programming, you will still read the following text, and then delete the code further, but this time you have to find a different way

2. Delete a lot of unnecessary private member variables and use "impl" instead ” Method

2.1. Use the "impl" implementation to write code and reduce the compilation dependency of client code. The

impl method is simply to put all the private member variables of the class into an impl class, and then keep only one private member variable of this class. impl* pointer, the code is as follows:
C++ code
// file old.h 
class old { 
  // public and protected members 
  // public and protected members 
private: 
  // private members, as long as any header file changes or the number of members increases , 
  // reduce, all clients referencing old.h must be recompiled 
  // private members; whenever these change, 
  // all client code must be recompiled 
}; 

http://tinypic.com/useralbum.php?ua=QnrDhDRffRJRWoifOqS884h4l5k2TGxc
http://tinypic.com/useralbum.php?ua=QnrDhDRffRIP79yy1jGM74h4l5k2TGxc
http://tinypic.com/useralbum.php?ua=QnrDhDRffRIcjT%2BTW1VbA4h4l5k2TGxc
http://tinypic.com/useralbum.php?ua=QnrDhDRffRIVb9NGM5UkdYh4l5k2TGxc
http://tinypic.com/useralbum.php?ua=QnrDhDRffRLKyzvUXGmvk4h4l5k2TGxc
http://tinypic.com/useralbum.php?ua=QnrDhDRffRLSYWxRwnULp4h4l5k2TGxc
http://tinypic.com/useralbum.php?ua=QnrDhDRffRKZRxRpj%2BJWo4h4l5k2TGxc
http://tinypic.com/useralbum.php?ua=QnrDhDRffRLTOyT1bFzHCoh4l5k2TGxc
http://tinypic.com/useralbum.php?ua=QnrDhDRffRLgOX7z6BRBJYh4l5k2TGxc
http://tinypic.com/useralbum.php?ua=QnrDhDRffRInd9ASv1sWRYh4l5k2TGxc
http://tinypic.com/useralbum.php?ua=QnrDhDRffRLkMdIPs%2F9AHoh4l5k2TGxc
http://tinypic.com/useralbum.php?ua=QnrDhDRffRK%2Fv91xo3azWIh4l5k2TGxc
http://tinypic.com/useralbum.php?ua=QnrDhDRffRJxBhHJw7h4T4h4l5k2TGxc
http://tinypic.com/useralbum.php?ua=QnrDhDRffRJ6TZfCkNfoL4h4
_ /tinypic.com/useralbum.php?ua=QnrDhDRffRIVb9NGM5UkdYh4l5k2TGxc
http://tinypic.com/useralbum.php?ua=QnrDhDRffRIeAom51USCIYh4l5k2TGxc rewritten as this:
C++ code
// file old.h 
class old { 
  // public and protected members 
  // public and protected members 
private: 
  class oldImpl* pimpl_; 
  // Replace all the original private member variables with this impl pointer, the pointer can be compiled and passed only by forward declaration, 
  // This writing method puts the forward declaration and definition pointer in the Together, it's totally possible. 
  // Of course, you can also write separately 
  // a pointer to a forward-declared class 
}; 
  
// file old.cpp 
struct oldImpl { 
  // The real member variables are hidden here, change at will, the client code does not need to be recompiled 
  // 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, please write a class test. That's what I did. Of course, everything has advantages and disadvantages. Here's a simple comparison:



After changing to impl, the implementation looks like this:
C++ code
/ / Only file and cx 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 here 
      }; 
        inline std::ostream& operator<<( std::ostream& os,const old& old_val ) 
       { return old_val.print(os); } 
  
//implementation file old.cpp 
class oldimpl{ 
std::list<cx> cx_list_; 
deduce dudece_d_; 
}; 

3. Delete unnecessary inheritance between classes Object

-oriented provides Inherit this mechanism, but do not abuse inheritance. The inheritance of old class is one of the abuses, class old inherits the file and db classes, inheriting file is public inheritance, inheriting db is private inheritance

, inheriting file is understandable, because there is virtual in file Function, old needs to redefine it, but according to our assumption, only file and cx have virtual functions, how to explain private inheritance db? ! Then the only possible reason is:

through private inheritance - so that a class cannot be used as a base class to derive other classes, similar to the function of the final keyword in Java, but from the example, it is obviously not intended, so this private inheritance is completely Not necessary, you should use the included method instead to use the functions provided by the db class,

Delete the "db.h" header file, and put the instance of db into the impl class. The final class is as follows:
C++ code
// Only use file and cx with 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 here 
      }; 
        inline std::ostream& operator<<( std::ostream& os,const old& old_val ) 
       { return old_val.print(os); } 
  
//implementation file old.cpp 
class oldimpl{ 
std::list<cx> cx_list_; 
deduce        dudece_d_; 
}; 

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326694276&siteId=291194637