Minimize Code in HeadersDon't include headers you don't need. Especially in headers.I've seen several places where a header will include something, like <deque> or "googleurl/src/gurl.h" and then not use the std::deque or GURL in the file. These are probably oversights from previous refactorings or reorganizations where the files used to be necessary, but they should be fixed whenever they are seen.Forward declare classes instead of including headers.You can use forward declarations in all the following cases:class Forward; But you can't forward declare in other situations:
Whenever you can forward declare, you should forward declare instead of including a header. Move inner classes into the implementation.You can also forward declare classes inside a class:class Whatever { Any headers that DataStruct needed no longer need to be included in the header file and only need to be included in the implementation. This will often let you pull headers includes out of the header. For reference, the syntax in the implementation file is: struct Whatever::DataStruct { Note that sometimes you can't do this because a handful of STL data structures require the full definition at declaration time (most notably, std::deque and the STL adapters that wrap it). Move static implementation details to the implementation whenever possible.If you have the class in a header file:#include "BigImplementationDetail.h" You should try to move that from a class member into the anonymous namespace in the implementation file: namespace { That way, people who don't use your interface don't need to know about or care about BigImplementationDetail. You can do this for helper functions that have hard to forward declare types, too. Stop inlining codeBACKGROUND: We're doing too much inlining. Remember that definitions in classes are requested to be inlined. Remember that asking the compiler to inline a method is a suggestion, one that's often ignored by the compiler. A compiler that never inlined anything would be perfectly standards compliant. Every file that has to use an inline method will also emit a function version in the resulting .o, even if the method was inlined. (This is to support function pointer behaviour properly.)class InlinedMethods {
Anything more than a few operations on integral data types will probably not be inlined by the compiler. Remember that inline is a suggestion, and that you're just adding crud to the .o files which the linker will need to do work to resolve. If the method deals with implementation details, there's also a good chance that you could eliminate some included headers in the header.Stop inlining constructors and destructors.Constructors and destructors are often significantly more complex than you think they are, especially if your class has any non-POD data members. Many STL classes have inlined constructors/destructors which may be copied into your function body. Because the bodies of these appear to be empty, they often seem like trivial functions that can safely be inlined. Don't give in to this temptation. Define them in the implementation file unless you really need them to be inlined. Even if they do nothing now, someone could later add something seemingly-trivial to the class and make your hundreds of inlined destructors much more complex.For more information, read Item 30 in Effective C++. Even worse though, inlining constructors/destructors prevents you from using forward declared variables. class Forward; When you CAN inline constructors and destructors.The above case had two class members and that's a large part of the reason it's more complex than it seems. There are cases where it is better to have an inline constructor and no destructor.
If you aren't sure, than you probably shouldn't try this. You CAN inline virtual destructors in pure abstract base classes.For example, you don't have to make a CC file for this:
Stop inlining virtual methods.You can't inline virtual methods under most circumstances, even if the method would otherwise be inlined because it's very short. The compiler must do runtime dispatch on any virtual method where the compiler doesn't know the object's complete type, which rules out the majority of cases where you have an object.Static variablesInitialization of function-scope static variables is thread-unsafe in chromium, even on compilers/platforms such as gcc/linux where such idioms are normally safe. Background can be found in this thread. The majority of Chrome code is intended to be single-threaded, where this presents no problem. When in multi-threaded code, however, the right answer is usually to use a base::LazyInstance. |
