野外求生夫妻挡之艾图:Google C++ Style Guide

来源:百度文库 编辑:九乡新闻网 时间:2024/04/29 16:20:35

Google C++ Style Guide

Revision 3.188

Benjy Weinberger
Craig Silverstein
Gregory Eitzmann
Mark Mentovai
Tashana Landray

Each style point has a summary for which additional information is availableby toggling the accompanying arrow button that looks this way:▽.You may toggle all summaries with the big arrow button:

▽Toggle all summariesTable of Contents Header Files The #define Guard Header File Dependencies Inline Functions The -inl.h Files Function Parameter Ordering Names and Order of Includes Scoping Namespaces Nested Classes Nonmember, Static Member, and Global Functions Local Variables Static and Global Variables Classes Doing Work in Constructors Default Constructors Explicit Constructors Copy Constructors Structs vs. Classes Inheritance Multiple Inheritance Interfaces Operator Overloading Access Control Declaration Order Write Short Functions Google-Specific Magic Smart Pointers cpplint Other C++ Features Reference Arguments Function Overloading Default Arguments Variable-Length Arrays and alloca() Friends Exceptions Run-Time Type Information (RTTI) Casting Streams Preincrement and Predecrement Use of const Integer Types 64-bit Portability Preprocessor Macros 0 and NULL sizeof Boost C++0x Naming General Naming Rules File Names Type Names Variable Names Constant Names Function Names Namespace Names Enumerator Names Macro Names Exceptions to Naming Rules Comments Comment Style File Comments Class Comments Function Comments Variable Comments Implementation Comments Punctuation, Spelling and Grammar TODO Comments Deprecation Comments Formatting Line Length Non-ASCII Characters Spaces vs. Tabs Function Declarations and Definitions Function Calls Conditionals Loops and Switch Statements Pointer and Reference Expressions Boolean Expressions Return Values Variable and Array Initialization Preprocessor Directives Class Format Constructor Initializer Lists Namespace Formatting Horizontal Whitespace Vertical Whitespace Exceptions to the Rules Existing Non-conformant Code Windows Code

Important Note

Displaying Hidden Details in this Guide

link▽This style guide contains many details that are initiallyhidden from view. They are marked by the triangle icon, which yousee here on your left. Click it now.You should see "Hooray" appear below.

Hooray! Now you know you can expand points to get moredetails. Alternatively, there's an "expand all" at thetop of this document.

Background

C++ is the main development languageused by many of Google's open-sourceprojects.As every C++ programmer knows, the language has many powerful features,but this power brings with it complexity, which in turn can make codemore bug-prone and harder to read and maintain.

The goal of this guide is to manage this complexity by describingin detail the dos and don'ts of writing C++code. These rules exist tokeepthecode base manageable while still allowing coders to use C++ languagefeatures productively.

Style, also known as readability, is what we call theconventions that govern our C++ code. The term Style is a bit of amisnomer, since these conventions cover far more than just sourcefile formatting.

One way in which we keep the code base manageable is by enforcingconsistency.It is very important that anyprogrammerbe able to look at another's code and quickly understand it.Maintaining a uniform style and following conventions means that we canmore easily use "pattern-matching" to infer what various symbols areand what invariants are true about them. Creating common, requiredidioms and patterns makes code much easier to understand. In somecases there might be good arguments for changing certain stylerules, but we nonetheless keep things as they are in order topreserve consistency.

Another issue this guide addresses is that of C++ feature bloat.C++ is a huge language with many advanced features. In some caseswe constrain, or even ban, use of certain features. We do this tokeep code simple and to avoid the various common errors andproblems that these features can cause. This guide lists thesefeatures and explains why their use is restricted.

Open-source projects developed by Googleconform to the requirements in this guide.

Note that this guide is not a C++ tutorial: we assume that thereader is familiar with the language.

Header Files

In general, every .cc file should have an associated.h file. There are some common exceptions, such asunittestsand small .cc files containing just a main()function.

Correct use of header files can make a huge difference to thereadability, size and performance of your code.

The following rules will guide you through the various pitfalls ofusing header files.

The #define Guard

link▽All header files should have #define guards toprevent multiple inclusion. The format of the symbol nameshould be___H_.

To guarantee uniqueness, they should be based on the full pathin a project's source tree. For example, the filefoo/src/bar/baz.h in project foo shouldhave the following guard:

#ifndef FOO_BAR_BAZ_H_#define FOO_BAR_BAZ_H_...#endif  // FOO_BAR_BAZ_H_

Header File Dependencies

link▽Don't use an #include when a forward declarationwould suffice.

When you include a header file you introduce a dependency thatwill cause your code to be recompiled whenever the header filechanges. If your header file includes other header files, anychange to those files will cause any code that includes yourheader to be recompiled. Therefore, we prefer to minimizeincludes, particularly includes of header files in otherheader files.

You can significantly reduce the number of header files youneed to include in your own header files by using forwarddeclarations. For example, if your header file uses theFile class in ways that do not require access tothe declaration of the File class, your headerfile can just forward declare class File; insteadof having to #include "file/base/file.h".

How can we use a class Foo in a header filewithout access to its definition?

  • We can declare data members of type Foo* or Foo&.
  • We can declare (but not define) functions with arguments, and/or return values, of type Foo. (One exception is if an argument Foo or const Foo& has a non-explicit, one-argument constructor, in which case we need the full definition to support automatic type conversion.)
  • We can declare static data members of type Foo. This is because static data members are defined outside the class definition.

On the other hand, you must include the header file forFoo if your class subclasses Foo orhas a data member of type Foo.

Sometimes it makes sense to have pointer (or better,scoped_ptr)members instead of object members. However, this complicates codereadability and imposes a performance penalty, so avoid doingthis transformation if the only purpose is to minimize includesin header files.

Of course, .cc files typically do require thedefinitions of the classes they use, and usually have toinclude several header files.

Note:If you use a symbol Foo in your source file, youshould bring in a definition for Foo yourself,either via an #include or via a forward declaration. Do notdepend on the symbol being brought in transitively via headersnot directly included. One exception is if Foois used in myfile.cc, it's ok to #include (orforward-declare) Foo in myfile.h,instead of myfile.cc.

Inline Functions

link▽Define functions inline only when they are small, say, 10 linesor less.

Definition: You can declare functions in a way that allows the compiler toexpand them inline rather than calling them through the usualfunction call mechanism.

Pros: Inlining a function can generate more efficient object code,as long as the inlined function is small. Feel free to inlineaccessors and mutators, and other short, performance-criticalfunctions.

Cons: Overuse of inlining can actually make programs slower.Depending on a function's size, inlining it can cause the codesize to increase or decrease. Inlining a very small accessorfunction will usually decrease code size while inlining a verylarge function can dramatically increase code size. On modernprocessors smaller code usually runs faster due to better useof the instruction cache.

Decision:

A decent rule of thumb is to not inline a function if it ismore than 10 lines long. Beware of destructors, which areoften longer than they appear because of implicit member-and base-destructor calls!

Another useful rule of thumb: it's typically not costeffective to inline functions with loops or switchstatements (unless, in the common case, the loop or switchstatement is never executed).

It is important to know that functions are not alwaysinlined even if they are declared as such; for example,virtual and recursive functions are not normally inlined.Usually recursive functions should not be inline. The mainreason for making a virtual function inline is to place itsdefinition in the class, either for convenience or todocument its behavior, e.g., for accessors and mutators.

 

The -inl.h Files

link▽You may use file names with a -inl.h suffix to definecomplex inline functions when needed.

The definition of an inline function needs to be in a headerfile, so that the compiler has the definition available forinlining at the call sites. However, implementation codeproperly belongs in .cc files, and we do not liketo have much actual code in .h files unless thereis a readability or performance advantage.

If an inline function definition is short, with very little,if any, logic in it, you should put the code in your.h file. For example, accessors and mutatorsshould certainly be inside a class definition. More complexinline functions may also be put in a .h file forthe convenience of the implementer and callers, though if thismakes the .h file too unwieldy you can insteadput that code in a separate -inl.h file.This separates the implementation from the class definition,while still allowing the implementation to be included wherenecessary.

Another use of -inl.h files is for definitions offunction templates. This can be used to keep your templatedefinitions easy to read.

Do not forget that a -inl.h file requires a#define guard justlike any other header file.

Function Parameter Ordering

link▽When defining a function, parameter order is: inputs,then outputs.

Parameters to C/C++ functions are either input to thefunction, output from the function, or both. Input parametersare usually values or const references, while outputand input/output parameters will be non-constpointers. When ordering function parameters, put all input-onlyparameters before any output parameters. In particular, do not addnew parameters to the end of the function just because they arenew; place new input-only parameters before the outputparameters.

This is not a hard-and-fast rule. Parameters that are bothinput and output (often classes/structs) muddy the waters,and, as always, consistency with related functions may requireyou to bend the rule.

Names and Order of Includes

link▽Use standard order for readability and to avoid hiddendependencies: C library, C++ library,other libraries' .h, yourproject's.h.

All of a project's header files should belisted as descendants of the project's source directorywithout use of UNIX directory shortcuts . (the currentdirectory) or .. (the parent directory). Forexample,google-awesome-project/src/base/logging.hshould be included as

#include "base/logging.h"

In dir/foo.cc or dir/foo_test.cc,whose main purpose is to implement or test the stuff indir2/foo2.h, order your includes asfollows:

  1. dir2/foo2.h (preferred location — see details below).
  2. C system files.
  3. C++ system files.
  4. Other libraries' .h files.
  5. Your project's .h files.

The preferred ordering reduces hidden dependencies. We wantevery header file to be compilable on its own. The easiestway to achieve this is to make sure that every one of them isthe first .h file #included in some.cc.

dir/foo.cc anddir2/foo2.h are often in the samedirectory (e.g. base/basictypes_test.cc andbase/basictypes.h), but can be in differentdirectories too.

Within each section it is nice to order the includesalphabetically.

For example, the includes ingoogle-awesome-project/src/foo/internal/fooserver.ccmight look like this:

#include "foo/public/fooserver.h"  // Preferred location.#include #include #include #include #include "base/basictypes.h"#include "base/commandlineflags.h"#include "foo/public/bar.h"

Scoping

Namespaces

link▽Unnamed namespaces in .cc files are encouraged. Withnamed namespaces, choose the name based on theproject, and possibly its path.Do not use a using-directive.

Definition: Namespaces subdivide the global scope into distinct, namedscopes, and so are useful for preventing name collisions inthe global scope.

Pros:

Namespaces provide a (hierarchical) axis of naming, inaddition to the (also hierarchical) name axis provided byclasses.

For example, if two different projects have a classFoo in the global scope, these symbols maycollide at compile time or at runtime. If each projectplaces their code in a namespace, project1::Fooand project2::Foo are now distinct symbols thatdo not collide.

 

Cons:

Namespaces can be confusing, because they provide anadditional (hierarchical) axis of naming, in addition to the(also hierarchical) name axis provided by classes.

Use of unnamed spaces in header files can easily causeviolations of the C++ One Definition Rule (ODR).

 

Decision:

Use namespaces according to the policy described below.

Unnamed Namespaces

  • Unnamed namespaces are allowed and even encouraged in .cc files, to avoid runtime naming conflicts:
    namespace {                           // This is in a .cc file.    // The content of a namespace is not indented    enum { kUnused, kEOF, kError };       // Commonly used tokens.    bool AtEof() { return pos_ == kEOF; }  // Uses our namespace's EOF.    }  // namespace

    However, file-scope declarations that are associated with a particular class may be declared in that class as types, static data members or static member functions rather than as members of an unnamed namespace. Terminate the unnamed namespace as shown, with a comment // namespace.

  • Do not use unnamed namespaces in .h files.

 

Named Namespaces

Named namespaces should be used as follows:

  • Namespaces wrap the entire source file after includes, gflags definitions/declarations, and forward declarations of classes from other namespaces:
    // In the .h file    namespace mynamespace {    // All declarations are within the namespace scope.    // Notice the lack of indentation.    class MyClass {    public:    ...    void Foo();    };    }  // namespace mynamespace
    // In the .cc file    namespace mynamespace {    // Definition of functions is within scope of the namespace.    void MyClass::Foo() {    ...    }    }  // namespace mynamespace

    The typical .cc file might have more complex detail, including the need to reference classes in other namespaces.

    #include "a.h"    DEFINE_bool(someflag, false, "dummy flag");    class C;  // Forward declaration of class C in the global namespace.    namespace a { class A; }  // Forward declaration of a::A.    namespace b {    ...code for b...         // Code goes against the left margin.    }  // namespace b
  • Do not declare anything in namespace std, not even forward declarations of standard library classes. Declaring entities in namespace std is undefined behavior, i.e., not portable. To declare entities from the standard library, include the appropriate header file.
  • You may not use a using-directive to make all names from a namespace available.
    // Forbidden -- This pollutes the namespace.    using namespace foo;
  • You may use a using-declaration anywhere in a .cc file, and in functions, methods or classes in .h files.
    // OK in .cc files.    // Must be in a function, method or class in .h files.    using ::foo::bar;
  • Namespace aliases are allowed anywhere in a .cc file, anywhere inside the named namespace that wraps an entire .h file, and in functions and methods.
    // Shorten access to some commonly used names in .cc files.    namespace fbz = ::foo::bar::baz;    // Shorten access to some commonly used names (in a .h file).    namespace librarian {    // The following alias is available to all files including    // this header (in namespace librarian):    // alias names should therefore be chosen consistently    // within a project.    namespace pd_s = ::pipeline_diagnostics::sidetable;    inline void my_inline_function() {    // namespace alias local to a function (or method).    namespace fbz = ::foo::bar::baz;    ...    }    }  // namespace librarian

    Note that an alias in a .h file is visible to everyone #including that file, so public headers (those available outside a project) and headers transitively #included by them, should avoid defining aliases, as part of the general goal of keeping public APIs as small as possible.

 

 

Nested Classes

link▽Although you may use public nested classes when they are part ofan interface, consider a namespace tokeep declarations out of the global scope.

Definition: A class can define another class within it; this is alsocalled a member class.

class Foo {private:// Bar is a member class, nested within Foo.class Bar {...};};

 

Pros: This is useful when the nested (or member) class is only usedby the enclosing class; making it a member puts it in theenclosing class scope rather than polluting the outer scopewith the class name. Nested classes can be forward declaredwithin the enclosing class and then defined in the.cc file to avoid including the nested classdefinition in the enclosing class declaration, since thenested class definition is usually only relevant to theimplementation.

Cons: Nested classes can be forward-declared only within thedefinition of the enclosing class. Thus, any header filemanipulating a Foo::Bar* pointer will have toinclude the full class declaration for Foo.

Decision: Do not make nested classes public unless they are actuallypart of the interface, e.g., a class that holds a set ofoptions for some method.

Nonmember, Static Member, and Global Functions

link▽Prefer nonmember functions within a namespace or static memberfunctions to global functions; use completely global functionsrarely.

Pros: Nonmember and static member functions can be useful in somesituations. Putting nonmember functions in a namespace avoidspolluting the global namespace.

Cons: Nonmember and static member functions may make more sense asmembers of a new class, especially if they access externalresources or have significant dependencies.

Decision:

Sometimes it is useful, or even necessary, to define afunction not bound to a class instance. Such a function canbe either a static member or a nonmember function.Nonmember functions should not depend on external variables,and should nearly always exist in a namespace. Rather thancreating classes only to group static member functions whichdo not share static data, usenamespaces instead.

Functions defined in the same compilation unit as productionclasses may introduce unnecessary coupling and link-timedependencies when directly called from other compilationunits; static member functions are particularly susceptibleto this. Consider extracting a new class, or placing thefunctions in a namespace possibly in a separate library.

If you must define a nonmember function and it is onlyneeded in its .cc file, use an unnamednamespace or staticlinkage (eg static int Foo() {...}) to limitits scope.

 

Local Variables

link▽Place a function's variables in the narrowest scope possible,and initialize variables in the declaration.

C++ allows you to declare variables anywhere in a function.We encourage you to declare them in as local a scope aspossible, and as close to the first use as possible. Thismakes it easier for the reader to find the declaration and seewhat type the variable is and what it was initialized to. Inparticular, initialization should be used instead ofdeclaration and assignment, e.g.

int i;i = f();      // Bad -- initialization separate from declaration.
int j = g();  // Good -- declaration has initialization.

Note that gcc implements for (int i = 0; i< 10; ++i) correctly (the scope of i isonly the scope of the for loop), so you can thenreuse i in another for loop in thesame scope. It also correctly scopes declarations inif and while statements, e.g.

while (const char* p = strchr(str, '/')) str = p + 1;

There is one caveat: if the variable is an object, itsconstructor is invoked every time it enters scope and iscreated, and its destructor is invoked every time it goesout of scope.

// Inefficient implementation:for (int i = 0; i < 1000000; ++i) {Foo f;  // My ctor and dtor get called 1000000 times each.f.DoSomething(i);}

It may be more efficient to declare such a variable used in aloop outside that loop:

Foo f;  // My ctor and dtor get called once each.for (int i = 0; i < 1000000; ++i) {f.DoSomething(i);}

Static and Global Variables

link▽Static or global variables of class type are forbidden: they causehard-to-find bugs due to indeterminate order of construction anddestruction.

Objects with static storage duration, including global variables,static variables, static class member variables, and function staticvariables, must be Plain Old Data (POD): only ints, chars, floats, orpointers, or arrays/structs of POD.

The order in which class constructors and initializers forstatic variables are called is only partially specified in C++ and caneven change from build to build, which can cause bugs that are difficultto find. Therefore in addition to banning globals of class type, we donot allow static POD variables to be initialized with the result of afunction, unless that function (such as getenv(), or getpid()) does notitself depend on any other globals.

Likewise, the order in which destructors are called is defined to be thereverse of the order in which the constructors were called. Sinceconstructor order is indeterminate, so is destructor order.For example, at program-end time a static variable might havebeen destroyed, but code still running -- perhaps in another thread --tries to access it and fails. Or the destructor for a static 'string'variable might be run prior to the destructor for another variable thatcontains a reference to that string.

As a result we only allow static variables to contain POD data. Thisrule completely disallows vector (use C arrays instead), orstring (use const char []).

If you need a static or global variable of a class type, considerinitializing a pointer (which will never be freed), from either yourmain() function or from pthread_once(). Note that this must be a rawpointer, not a "smart" pointer, since the smart pointer's destructorwill have the order-of-destructor issue that we are trying to avoid.

Classes

Classes are the fundamental unit of code in C++. Naturally, we usethem extensively. This section lists the main dos and don'ts youshould follow when writing a class.

Doing Work in Constructors

link▽In general, constructors should merely set member variables to theirinitial values. Any complex initialization should go in an explicitInit() method.

Definition: It is possible to perform initialization in the body of theconstructor.

Pros: Convenience in typing. No need to worry about whether theclass has been initialized or not.

Cons: The problems with doing work in constructors are:

  • There is no easy way for constructors to signal errors, short of using exceptions (which are forbidden).
  • If the work fails, we now have an object whose initialization code failed, so it may be an indeterminate state.
  • If the work calls virtual functions, these calls will not get dispatched to the subclass implementations. Future modification to your class can quietly introduce this problem even if your class is not currently subclassed, causing much confusion.
  • If someone creates a global variable of this type (which is against the rules, but still), the constructor code will be called before main(), possibly breaking some implicit assumptions in the constructor code. For instance, gflags will not yet have been initialized.

 

Decision: If your object requires non-trivial initialization, considerhaving an explicit Init() method. In particular,constructors should not call virtual functions, attempt to raiseerrors, access potentially uninitialized global variables, etc.

Default Constructors

link▽You must define a default constructor if your class definesmember variables and has no other constructors. Otherwise thecompiler will do it for you, badly.

Definition: The default constructor is called when we new aclass object with no arguments. It is always called whencalling new[] (for arrays).

Pros: Initializing structures by default, to hold "impossible"values, makes debugging much easier.

Cons: Extra work for you, the code writer.

Decision:

If your class defines member variables and has no otherconstructors you must define a default constructor (one thattakes no arguments). It should preferably initialize theobject in such a way that its internal state is consistentand valid.

The reason for this is that if you have no otherconstructors and do not define a default constructor, thecompiler will generate one for you. This compilergenerated constructor may not initialize your objectsensibly.

If your class inherits from an existing class but you add nonew member variables, you are not required to have a defaultconstructor.

 

Explicit Constructors

link▽Use the C++ keyword explicit for constructors withone argument.

Definition: Normally, if a constructor takes one argument, it can be usedas a conversion. For instance, if you defineFoo::Foo(string name) and then pass a string to afunction that expects a Foo, the constructor willbe called to convert the string into a Foo andwill pass the Foo to your function for you. Thiscan be convenient but is also a source of trouble when thingsget converted and new objects created without you meaning themto. Declaring a constructor explicit prevents itfrom being invoked implicitly as a conversion.

Pros: Avoids undesirable conversions.

Cons: None.

Decision:

We require all single argument constructors to beexplicit. Always put explicit in front ofone-argument constructors in the class definition:explicit Foo(string name);

The exception is copy constructors, which, in the rarecases when we allow them, should probably not beexplicit.Classes that are intended to betransparent wrappers around other classes are alsoexceptions.Such exceptions should be clearly marked with comments.

 

Copy Constructors

link▽Provide a copy constructor and assignment operator only when necessary.Otherwise, disable them with DISALLOW_COPY_AND_ASSIGN.

Definition: The copy constructor and assignment operator are used to create copiesof objects. The copy constructor is implicitly invoked by thecompiler in some situations, e.g. passing objects by value.

Pros: Copy constructors make it easy to copy objects. STLcontainers require that all contents be copyable andassignable. Copy constructors can be more efficient thanCopyFrom()-style workarounds because they combineconstruction with copying, the compiler can elide them in somecontexts, and they make it easier to avoid heap allocation.

Cons: Implicit copying of objects in C++ is a rich source of bugsand of performance problems. It also reduces readability, asit becomes hard to track which objects are being passed aroundby value as opposed to by reference, and therefore wherechanges to an object are reflected.

Decision:

Few classes need to be copyable. Most should have neither acopy constructor nor an assignment operator. In many situations,a pointer or reference will work just as well as a copied value,with better performance. For example, you can pass functionparameters by reference or pointer instead of by value, and you canstore pointers rather than objects in an STL container.

If your class needs to be copyable, prefer providing a copy method,such as CopyFrom() or Clone(), rather thana copy constructor, because such methods cannot be invokedimplicitly. If a copy method is insufficient in your situation(e.g. for performance reasons, or because your class needs to bestored by value in an STL container), provide both a copyconstructor and assignment operator.

If your class does not need a copy constructor or assignmentoperator, you must explicitly disable them.To do so, add dummy declarations for the copy constructor andassignment operator in the private: section of yourclass, but do not provide any corresponding definition (so thatany attempt to use them results in a link error).

For convenience, a DISALLOW_COPY_AND_ASSIGN macrocan be used:

// A macro to disallow the copy constructor and operator= functions// This should be used in the private: declarations for a class#define DISALLOW_COPY_AND_ASSIGN(TypeName) TypeName(const TypeName&);               void operator=(const TypeName&)

Then, in class Foo:

class Foo {public:Foo(int f);~Foo();private:DISALLOW_COPY_AND_ASSIGN(Foo);};

 

Structs vs. Classes

link▽Use a struct only for passive objects that carry data;everything else is a class.

The struct and class keywords behavealmost identically in C++. We add our own semantic meaningsto each keyword, so you should use the appropriate keyword forthe data-type you're defining.

structs should be used for passive objects that carrydata, and may have associated constants, but lack any functionalityother than access/setting the data members. Theaccessing/setting of fields is done by directly accessing thefields rather than through method invocations. Methods shouldnot provide behavior but should only be used to set up thedata members, e.g., constructor, destructor,Initialize(), Reset(),Validate().

If more functionality is required, a class is moreappropriate. If in doubt, make it a class.

For consistency with STL, you can use structinstead of class for functors and traits.

Note that member variables in structs and classes havedifferent naming rules.

Inheritance

link▽Composition is often more appropriate than inheritance. Whenusing inheritance, make it public.

Definition: When a sub-class inherits from a base class, it includes thedefinitions of all the data and operations that the parentbase class defines. In practice, inheritance is used in twomajor ways in C++: implementation inheritance, in whichactual code is inherited by the child, and interface inheritance, in which onlymethod names are inherited.

Pros: Implementation inheritance reduces code size by re-using thebase class code as it specializes an existing type. Becauseinheritance is a compile-time declaration, you and thecompiler can understand the operation and detect errors.Interface inheritance can be used to programmatically enforcethat a class expose a particular API. Again, the compilercan detect errors, in this case, when a class does not definea necessary method of the API.

Cons: For implementation inheritance, because the code implementinga sub-class is spread between the base and the sub-class, itcan be more difficult to understand an implementation. Thesub-class cannot override functions that are not virtual, sothe sub-class cannot change implementation. The base classmay also define some data members, so that specifies physicallayout of the base class.

Decision:

All inheritance should be public. If you want todo private inheritance, you should be including an instance ofthe base class as a member instead.

Do not overuse implementation inheritance. Composition isoften more appropriate. Try to restrict use of inheritanceto the "is-a" case: Bar subclassesFoo if it can reasonably be said thatBar "is a kind of" Foo.

Make your destructor virtual if necessary. Ifyour class has virtual methods, its destructorshould be virtual.

Limit the use of protected to those memberfunctions that might need to be accessed from subclasses.Note that data members shouldbe private.

When redefining an inherited virtual function, explicitlydeclare it virtual in the declaration of thederived class. Rationale: If virtual isomitted, the reader has to check all ancestors of theclass in question to determine if the function is virtualor not.

 

Multiple Inheritance

link▽Only very rarely is multiple implementation inheritance actuallyuseful. We allow multiple inheritance only when at most one ofthe base classes has an implementation; all other base classesmust be pure interface classes taggedwith the Interface suffix.

Definition: Multiple inheritance allows a sub-class to have more than onebase class. We distinguish between base classes that arepure interfaces and those that have animplementation.

Pros: Multiple implementation inheritance may let you re-use even more codethan single inheritance (see Inheritance).

Cons: Only very rarely is multiple implementationinheritance actually useful. When multiple implementationinheritance seems like the solution, you can usually find adifferent, more explicit, and cleaner solution.

Decision: Multiple inheritance is allowed only when all superclasses, with thepossible exception of the first one, are pureinterfaces. In order to ensure that they remain pure interfaces,they must end with the Interface suffix.

Note:There is an exception to thisrule on Windows.

 

Interfaces

link▽Classes that satisfy certain conditions are allowed, but not required, toend with an Interface suffix.

Definition:

A class is a pure interface if it meets the following requirements:

  • It has only public pure virtual ("= 0") methods and static methods (but see below for destructor).
  • It may not have non-static data members.
  • It need not have any constructors defined. If a constructor is provided, it must take no arguments and it must be protected.
  • If it is a subclass, it may only be derived from classes that satisfy these conditions and are tagged with the Interface suffix.

An interface class can never be directly instantiatedbecause of the pure virtual method(s) it declares. To makesure all implementations of the interface can be destroyedcorrectly, they must also declare a virtual destructor (inan exception to the first rule, this should not be pure). SeeStroustrup, The C++ Programming Language, 3rdedition, section 12.4 for details.

 

Pros: Tagging a class with the Interface suffix letsothers know that they must not add implemented methods or nonstatic data members. This is particularly important in the case ofmultiple inheritance.Additionally, the interface concept is already well-understood byJava programmers.

Cons: The Interface suffix lengthens the class name, whichcan make it harder to read and understand. Also, the interfaceproperty may be considered an implementation detail that shouldn'tbe exposed to clients.

Decision: A class may end with Interface only if it meets theabove requirements. We do not require the converse, however:classes that meet the above requirements are not required to endwith Interface.

Operator Overloading

link▽Do not overload operators except in rare, special circumstances.

Definition: A class can define that operators such as + and/ operate on the class as if it were a built-intype.

Pros: Can make code appear more intuitive because a class willbehave in the same way as built-in types (such asint). Overloaded operators are more playfulnames for functions that are less-colorfully named, such asEquals() or Add(). For sometemplate functions to work correctly, you may need to defineoperators.

Cons: While operator overloading can make code more intuitive, ithas several drawbacks:

  • It can fool our intuition into thinking that expensive operations are cheap, built-in operations.
  • It is much harder to find the call sites for overloaded operators. Searching for Equals() is much easier than searching for relevant invocations of ==.
  • Some operators work on pointers too, making it easy to introduce bugs. Foo + 4 may do one thing, while &Foo + 4 does something totally different. The compiler does not complain for either of these, making this very hard to debug.
Overloading also has surprising ramifications. For instance,if a class overloads unary operator&, itcannot safely be forward-declared.

 

Decision:

In general, do not overload operators. The assignment operator(operator=), in particular, is insidious andshould be avoided. You can define functions likeEquals() and CopyFrom() if youneed them. Likewise, avoid the dangerousunary operator& at all costs, if there'sany possibility the class might be forward-declared.

However, there may be rare cases where you need to overloadan operator to interoperate with templates or "standard" C++classes (such as operator<<(ostream&, constT&) for logging). These are acceptable if fullyjustified, but you should try to avoid these wheneverpossible. In particular, do not overload operator==or operator< just so that your class can beused as a key in an STL container; instead, you shouldcreate equality and comparison functor types when declaringthe container.

Some of the STL algorithms do require you to overloadoperator==, and you may do so in these cases,provided you document why.

See also Copy Constructorsand FunctionOverloading.

 

Access Control

link▽Make data members private, and provideaccess to them through accessor functions as needed (fortechnical reasons, we allow data members of a test fixture classto be protected when usingGoogle Test). Typically a variable would becalled foo_ and the accessor functionfoo(). You may also want a mutator functionset_foo().Exception: static const data members (typicallycalled kFoo) need not be private.

The definitions of accessors are usually inlined in the headerfile.

See also Inheritance and Function Names.

Declaration Order

link▽Use the specified order of declarations within a class:public: before private:, methodsbefore data members (variables), etc.

Your class definition should start with its public:section, followed by its protected: section andthen its private: section. If any of these sectionsare empty, omit them.

Within each section, the declarations generally should be inthe following order:

  • Typedefs and Enums
  • Constants (static const data members)
  • Constructors
  • Destructor
  • Methods, including static methods
  • Data Members (except static const data members)

Friend declarations should always be in the private section, andthe DISALLOW_COPY_AND_ASSIGN macro invocationshould be at the end of the private: section. Itshould be the last thing in the class. See Copy Constructors.

Method definitions in the corresponding .cc fileshould be the same as the declaration order, as much as possible.

Do not put large method definitions inline in the classdefinition. Usually, only trivial or performance-critical,and very short, methods may be defined inline. See Inline Functions for moredetails.

Write Short Functions

link▽Prefer small and focused functions.

We recognize that long functions are sometimes appropriate, sono hard limit is placed on functions length. If a functionexceeds about 40 lines, think about whether it can be brokenup without harming the structure of the program.

Even if your long function works perfectly now, someonemodifying it in a few months may add new behavior. This couldresult in bugs that are hard to find. Keeping your functionsshort and simple makes it easier for other people to read andmodify your code.

You could find long and complicated functions when workingwithsomecode. Do not be intimidated by modifying existingcode: if working with such a function proves to be difficult,you find that errors are hard to debug, or you want to use apiece of it in several different contexts, consider breakingup the function into smaller and more manageable pieces.

Google-Specific Magic

There are various tricks and utilities that we use to make C++code more robust, and various ways we use C++ that may differ fromwhat you see elsewhere.

Smart Pointers

link▽If you actually need pointer semantics, scoped_ptris great. You should only use std::tr1::shared_ptrwith a non-const referent when it is truly necessary to share ownershipof an object (e.g. inside an STL container). You should never useauto_ptr.

Definition: "Smart" pointers are objects that act like pointers, but automatemanagement of the underlying memory.

Pros: Smart pointers are extremely useful for preventing memory leaks, andare essential for writing exception-safe code. They also formalizeand document the ownership of dynamically allocated memory.

Cons: We prefer designs in which objects have single, fixed owners. Smartpointers which enable sharing or transfer of ownership can act as atempting alternative to a careful design of ownership semantics,leading to confusing code and even bugs in which memory is neverdeleted. The semantics of smart pointers (especiallyauto_ptr) can be nonobvious and confusing. Theexception-safety benefits of smart pointers are not decisive, sincewe do not allow exceptions.

Decision:

scoped_ptr
Straightforward and risk-free. Use wherever appropriate.
auto_ptr
Confusing and bug-prone ownership-transfer semantics. Do not use.
shared_ptr
Safe with const referents (i.e. shared_ptr). Reference-counted pointers with non-const referentscan occasionally be the best design, but try to rewrite with singleowners where possible.

 

cpplint

link▽Usecpplint.pyto detect style errors.

cpplint.pyis a tool that reads a source file andidentifies many style errors. It is not perfect, and has both falsepositives and false negatives, but it is still a valuable tool. Falsepositives can be ignored by putting // NOLINT atthe end of the line.

Some projects have instructions on how to run cpplint.pyfrom their project tools. If the project you are contributing to doesnot, you can download cpplint.py separately.

Other C++ Features

Reference Arguments

link▽All parameters passed by reference must be labeledconst.

Definition: In C, if a function needs to modify a variable, theparameter must use a pointer, eg int foo(int*pval). In C++, the function can alternativelydeclare a reference parameter: int foo(int&val).

Pros: Defining a parameter as reference avoids ugly code like(*pval)++. Necessary for some applications likecopy constructors. Makes it clear, unlike with pointers, thatNULL is not a possible value.

Cons: References can be confusing, as they have value syntax butpointer semantics.

Decision:

Within function parameter lists all references must beconst:

void Foo(const string &in, string *out);

In fact it is a very strong convention in Google code that inputarguments are values or const references whileoutput arguments are pointers. Input parameters may beconst pointers, but we never allownon-const reference parameters.

One case when you might want an input parameter to be aconst pointer is if you want to emphasize that theargument is not copied, so it must exist for the lifetime of theobject; it is usually best to document this in comments aswell. STL adapters such as bind2nd andmem_fun do not permit reference parameters, soyou must declare functions with pointer parameters in thesecases, too.

 

Function Overloading

link▽Use overloaded functions (including constructors) only if areader looking at a call site can get a good idea of what ishappening without having to first figure out exactly whichoverload is being called.

Definition:

You may write a function that takes aconst string& and overload it with another thattakes const char*.

class MyClass {public:void Analyze(const string &text);void Analyze(const char *text, size_t textlen);};

 

Pros: Overloading can make code more intuitive by allowing anidentically-named function to take different arguments. Itmay be necessary for templatized code, and it can beconvenient for Visitors.

Cons: If a function is overloaded by the argument types alone, areader may have to understand C++'s complex matching rules inorder to tell what's going on. Also many people are confusedby the semantics of inheritance if a derived class overridesonly some of the variants of a function.

Decision: If you want to overload a function, consider qualifying thename with some information about the arguments, e.g.,AppendString(), AppendInt() ratherthan just Append().

Default Arguments

link▽We do not allow default function parameters, except ina few uncommon situations explained below.

Pros: Often you have a function that uses lots of default values,but occasionally you want to override the defaults. Defaultparameters allow an easy way to do this without having todefine many functions for the rare exceptions.

Cons: People often figure out how to use anAPI by looking at existing code that uses it.Default parameters are more difficult to maintain becausecopy-and-paste from previous code may not reveal all theparameters. Copy-and-pasting of code segments can cause majorproblems when the default arguments are not appropriate forthe new code.

Decision:

Except as described below, we require all arguments to beexplicitly specified, to force programmers to consider the APIand the values they are passing for each argument rather thansilently accepting defaults they may not be aware of.

One specific exception is when default arguments are used tosimulate variable-length argument lists.

// Support up to 4 params by using a default empty AlphaNum.string StrCat(const AlphaNum &a,const AlphaNum &b = gEmptyAlphaNum,const AlphaNum &c = gEmptyAlphaNum,const AlphaNum &d = gEmptyAlphaNum);

 

Variable-Length Arrays and alloca()

link▽We do not allow variable-length arrays or alloca().

Pros: Variable-length arrays have natural-looking syntax. Bothvariable-length arrays and alloca() are veryefficient.

Cons: Variable-length arrays and alloca are not part of StandardC++. More importantly, they allocate a data-dependent amountof stack space that can trigger difficult-to-find memoryoverwriting bugs: "It ran fine on my machine, but diesmysteriously in production".

Decision: Use a safe allocator instead, such asscoped_ptr/scoped_array.

Friends

link▽We allow use of friend classes and functions,within reason.

Friends should usually be defined in the same file so that thereader does not have to look in another file to find uses ofthe private members of a class. A common use offriend is to have a FooBuilder classbe a friend of Foo so that it can construct theinner state of Foo correctly, without exposingthis state to the world. In some cases it may be useful tomake a unittest class a friend of the class it tests.

Friends extend, but do not break, the encapsulationboundary of a class. In some cases this is better than makinga member public when you want to give only one other classaccess to it. However, most classes should interact withother classes solely through their public members.

Exceptions

link▽We do not use C++ exceptions.

Pros:

  • Exceptions allow higher levels of an application to decide how to handle "can't happen" failures in deeply nested functions, without the obscuring and error-prone bookkeeping of error codes.
  • Exceptions are used by most other modern languages. Using them in C++ would make it more consistent with Python, Java, and the C++ that others are familiar with.
  • Some third-party C++ libraries use exceptions, and turning them off internally makes it harder to integrate with those libraries.
  • Exceptions are the only way for a constructor to fail. We can simulate this with a factory function or an Init() method, but these require heap allocation or a new "invalid" state, respectively.
  • Exceptions are really handy in testing frameworks.

 

Cons:

  • When you add a throw statement to an existing function, you must examine all of its transitive callers. Either they must make at least the basic exception safety guarantee, or they must never catch the exception and be happy with the program terminating as a result. For instance, if f() calls g() calls h(), and h throws an exception that f catches, g has to be careful or it may not clean up properly.
  • More generally, exceptions make the control flow of programs difficult to evaluate by looking at code: functions may return in places you don't expect. This causes maintainability and debugging difficulties. You can minimize this cost via some rules on how and where exceptions can be used, but at the cost of more that a developer needs to know and understand.
  • Exception safety requires both RAII and different coding practices. Lots of supporting machinery is needed to make writing correct exception-safe code easy. Further, to avoid requiring readers to understand the entire call graph, exception-safe code must isolate logic that writes to persistent state into a "commit" phase. This will have both benefits and costs (perhaps where you're forced to obfuscate code to isolate the commit). Allowing exceptions would force us to always pay those costs even when they're not worth it.
  • Turning on exceptions adds data to each binary produced, increasing compile time (probably slightly) and possibly increasing address space pressure.
  • The availability of exceptions may encourage developers to throw them when they are not appropriate or recover from them when it's not safe to do so. For example, invalid user input should not cause exceptions to be thrown. We would need to make the style guide even longer to document these restrictions!

 

Decision:

On their face, the benefits of using exceptions outweigh thecosts, especially in new projects. However, for existing code,the introduction of exceptions has implications on all dependentcode. If exceptions can be propagated beyond a new project, italso becomes problematic to integrate the new project intoexisting exception-free code. Because most existing C++ code atGoogle is not prepared to deal with exceptions, it iscomparatively difficult to adopt new code that generatesexceptions.

Given that Google's existing code is not exception-tolerant, thecosts of using exceptions are somewhat greater than the costs ina new project. The conversion process would be slow anderror-prone. We don't believe that the available alternatives toexceptions, such as error codes and assertions, introduce asignificant burden.

Our advice against using exceptions is not predicated onphilosophical or moral grounds, but practical ones.Because we'd like to use our open-sourceprojects at Google and it's difficult to do so if those projectsuse exceptions, we need to advise against exceptions in Googleopen-source projects as well.Things would probably be different if we had to do it all overagain from scratch.

There is an exception to thisrule (no pun intended) for Windows code.

 

Run-Time Type Information (RTTI)

link▽We do not use Run Time Type Information (RTTI).

Definition: RTTI allows a programmer to query the C++ class of anobject at run time.

Pros:

It is useful in some unittests. For example, it is useful intests of factory classes where the test has to verify that anewly created object has the expected dynamic type.

In rare circumstances, it is useful even outside oftests.

 

Cons: A query of type during run-time typically means adesign problem. If you need to know the type of anobject at runtime, that is often an indication thatyou should reconsider the design of your class.

Decision:

Do not use RTTI, except in unittests. If you find yourselfin need of writing code that behaves differently based onthe class of an object, consider one of the alternatives toquerying the type.

Virtual methods are the preferred way of executing differentcode paths depending on a specific subclass type. This putsthe work within the object itself.

If the work belongs outside the object and instead in someprocessing code, consider a double-dispatch solution, suchas the Visitor design pattern. This allows a facilityoutside the object itself to determine the type of classusing the built-in type system.

If you think you truly cannot use those ideas,you may use RTTI. But think twiceabout it. :-) Then think twice again.Do not hand-implement an RTTI-like workaround. The argumentsagainst RTTI apply just as much to workarounds like classhierarchies with type tags.

 

Casting

link▽Use C++ casts like static_cast<>(). Do not useother cast formats like int y = (int)x; orint y = int(x);.

Definition: C++ introduced a different cast system from C thatdistinguishes the types of cast operations.

Pros: The problem with C casts is the ambiguity of the operation;sometimes you are doing a conversion (e.g.,(int)3.5) and sometimes you are doing acast (e.g., (int)"hello"); C++ castsavoid this. Additionally C++ casts are more visible whensearching for them.

Cons: The syntax is nasty.

Decision:

Do not use C-style casts. Instead, use these C++-stylecasts.

  • Use static_cast as the equivalent of a C-style cast that does value conversion, or when you need to explicitly up-cast a pointer from a class to its superclass.
  • Use const_cast to remove the const qualifier (see const).
  • Use reinterpret_cast to do unsafe conversions of pointer types to and from integer and other pointer types. Use this only if you know what you are doing and you understand the aliasing issues.
  • Do not use dynamic_cast except in test code. If you need to know type information at runtime in this way outside of a unittest, you probably have a design flaw.

 

Streams

link▽Use streams only for logging.

Definition: Streams are a replacement for printf() andscanf().

Pros: With streams, you do not need to know the type of the objectyou are printing. You do not have problems with formatstrings not matching the argument list. (Though with gcc, youdo not have that problem with printf either.) Streamshave automatic constructors and destructors that open and close therelevant files.

Cons: Streams make it difficult to do functionality likepread(). Some formatting (particularly the commonformat string idiom %.*s) is difficult if notimpossible to do efficiently using streams without usingprintf-like hacks. Streams do not support operatorreordering (the %1s directive), which is helpful forinternationalization.

Decision:

Do not use streams, except where required by a logging interface.Use printf-like routines instead.

There are various pros and cons to using streams, but inthis case, as in many other cases, consistency trumps thedebate. Do not use streams in your code.

Extended Discussion

There has been debate on this issue, so this explains thereasoning in greater depth. Recall the Only One Wayguiding principle: we want to make sure that whenever wedo a certain type of I/O, the code looks the same in allthose places. Because of this, we do not want to allowusers to decide between using streams or usingprintf plus Read/Write/etc. Instead, we shouldsettle on one or the other. We made an exception for loggingbecause it is a pretty specialized application, and forhistorical reasons.

Proponents of streams have argued that streams are the obviouschoice of the two, but the issue is not actually so clear. Forevery advantage of streams they point out, there is anequivalent disadvantage. The biggest advantage is thatyou do not need to know the type of the object to beprinting. This is a fair point. But, there is adownside: you can easily use the wrong type, and thecompiler will not warn you. It is easy to make thiskind of mistake without knowing when using streams.

cout << this;  // Prints the addresscout << *this;  // Prints the contents

The compiler does not generate an error because<< has been overloaded. We discourageoverloading for just this reason.

Some say printf formatting is ugly and hard toread, but streams are often no better. Consider the followingtwo fragments, both with the same typo. Which is easier todiscover?

cerr << "Error connecting to '" << foo->bar()->hostname.first<< ":" << foo->bar()->hostname.second << ": " << strerror(errno);fprintf(stderr, "Error connecting to '%s:%u: %s",foo->bar()->hostname.first, foo->bar()->hostname.second,strerror(errno));

And so on and so forth for any issue you might bring up.(You could argue, "Things would be better with the rightwrappers," but if it is true for one scheme, is it notalso true for the other? Also, remember the goal is tomake the language smaller, not add yet more machinery thatsomeone has to learn.)

Either path would yield different advantages anddisadvantages, and there is not a clearly superiorsolution. The simplicity doctrine mandates we settle onone of them though, and the majority decision was onprintf + read/write.

 

 

Preincrement and Predecrement

link▽Use prefix form (++i) of the increment anddecrement operators with iterators and other template objects.

Definition: When a variable is incremented (++i ori++) or decremented (--i ori--) and the value of the expression is not used,one must decide whether to preincrement (decrement) orpostincrement (decrement).

Pros: When the return value is ignored, the "pre" form(++i) is never less efficient than the "post"form (i++), and is often more efficient. This isbecause post-increment (or decrement) requires a copy ofi to be made, which is the value of theexpression. If i is an iterator or othernon-scalar type, copying i could be expensive.Since the two types of increment behave the same when thevalue is ignored, why not just always pre-increment?

Cons: The tradition developed, in C, of using post-increment whenthe expression value is not used, especially in forloops. Some find post-increment easier to read, since the"subject" (i) precedes the "verb" (++),just like in English.

Decision: For simple scalar (non-object) values there is no reason toprefer one form and we allow either. For iterators and othertemplate types, use pre-increment.

Use of const

link▽We strongly recommend that you use const wheneverit makes sense to do so.

Definition: Declared variables and parameters can be preceded by thekeyword const to indicate the variables are notchanged (e.g., const int foo). Class functionscan have the const qualifier to indicate thefunction does not change the state of the class membervariables (e.g., class Foo { int Bar(char c) const;};).

Pros: Easier for people to understand how variables are being used.Allows the compiler to do better type checking, and,conceivably, generate better code. Helps people convincethemselves of program correctness because they know thefunctions they call are limited in how they can modify yourvariables. Helps people know what functions are safe to usewithout locks in multi-threaded programs.

Cons: const is viral: if you pass a constvariable to a function, that function must have constin its prototype (or the variable will need aconst_cast). This can be a particular problemwhen calling library functions.

Decision:

const variables, data members, methods andarguments add a level of compile-time type checking; itis better to detect errors as soon as possible.Therefore we strongly recommend that you useconst whenever it makes sense to do so:

  • If a function does not modify an argument passed by reference or by pointer, that argument should be const.
  • Declare methods to be const whenever possible. Accessors should almost always be const. Other methods should be const if they do not modify any data members, do not call any non-const methods, and do not return a non-const pointer or non-const reference to a data member.
  • Consider making data members const whenever they do not need to be modified after construction.

However, do not go crazy with const. Something likeconst int * const * const x; is likelyoverkill, even if it accurately describes how const x is.Focus on what's really useful to know: in this case,const int** x is probably sufficient.

The mutable keyword is allowed but is unsafewhen used with threads, so thread safety should be carefullyconsidered first.

 

Where to put the const

Some people favor the form int const *foo toconst int* foo. They argue that this is morereadable because it's more consistent: it keeps the rulethat const always follows the object it'sdescribing. However, this consistency argument doesn'tapply in this case, because the "don't go crazy" dictumeliminates most of the uses you'd have to be consistent with.Putting the const first is arguably more readable,since it follows English in putting the "adjective"(const) before the "noun" (int).

That said, while we encourage putting const first,we do not require it. But be consistent with the code aroundyou!

 

Integer Types

link▽Of the built-in C++ integer types, the only one usedis int. If a program needs a variable of a differentsize, usea precise-width integer type from, such as int16_t.

Definition: C++ does not specify the sizes of its integer types. Typicallypeople assume that short is 16 bits,int is 32 bits, long is 32 bits andlong long is 64 bits.

Pros: Uniformity of declaration.

Cons: The sizes of integral types in C++ can vary based on compilerand architecture.

Decision:

definestypes like int16_t, uint32_t,int64_t, etc.You should always use those in preference toshort, unsigned long long and thelike, when you need a guarantee on the size of an integer.Of the C integer types, only int should beused. When appropriate, you are welcome to use standardtypes like size_t and ptrdiff_t.

We use int very often, for integers we know are notgoing to be too big, e.g., loop counters. Use plain oldint for such things. You should assume that anint isat least 32 bits,but don't assume that it has more than 32 bits.If you need a 64-bit integer type, useint64_t oruint64_t.

For integers we know can be "big",useint64_t.

You should not use the unsigned integer types such asuint32_t,unless the quantity you are representing is really a bit patternrather than a number, or unless you need definedtwos-complement overflow. In particular, do not use unsignedtypes to say a number will never be negative. Instead, useassertions for this.

 

On Unsigned Integers

Some people, including some textbook authors, recommendusing unsigned types to represent numbers that are nevernegative. This is intended as a form of self-documentation.However, in C, the advantages of such documentation areoutweighed by the real bugs it can introduce. Consider:

for (unsigned int i = foo.Length()-1; i >= 0; --i) ...

This code will never terminate! Sometimes gcc will noticethis bug and warn you, but often it will not. Equally badbugs can occur when comparing signed and unsignedvariables. Basically, C's type-promotion scheme causesunsigned types to behave differently than one might expect.

So, document that a variable is non-negative usingassertions.Don't use an unsigned type.

 

64-bit Portability

link▽Code should be 64-bit and 32-bit friendly. Bear in mind problems ofprinting, comparisons, and structure alignment.
  • printf() specifiers for some types are not cleanly portable between 32-bit and 64-bit systems. C99 defines some portable format specifiers. Unfortunately, MSVC 7.1 does not understand some of these specifiers and the standard is missing a few, so we have to define our own ugly versions in some cases (in the style of the standard include file inttypes.h):

    // printf macros for size_t, in the style of inttypes.h    #ifdef _LP64    #define __PRIS_PREFIX "z"    #else    #define __PRIS_PREFIX    #endif    // Use these macros after a % in a printf format string    // to get correct 32/64 bit behavior, like this:    // size_t size = records.size();    // printf("%"PRIuS"\n", size);    #define PRIdS __PRIS_PREFIX "d"    #define PRIxS __PRIS_PREFIX "x"    #define PRIuS __PRIS_PREFIX "u"    #define PRIXS __PRIS_PREFIX "X"    #define PRIoS __PRIS_PREFIX "o"
    Type DO NOT use DO use Notes void * (or any pointer) %lx %p int64_t %qd, %lld %"PRId64" uint64_t %qu, %llu, %llx %"PRIu64", %"PRIx64" size_t %u %"PRIuS", %"PRIxS" C99 specifies %zu ptrdiff_t %d %"PRIdS" C99 specifies %zd

    Note that the PRI* macros expand to independent strings which are concatenated by the compiler. Hence if you are using a non-constant format string, you need to insert the value of the macro into the format, rather than the name. It is still possible, as usual, to include length specifiers, etc., after the % when using the PRI* macros. So, e.g. printf("x = %30"PRIuS"\n", x) would expand on 32-bit Linux to printf("x = %30" "u" "\n", x), which the compiler will treat as printf("x = %30u\n", x).

  • Remember that sizeof(void *) != sizeof(int). Use intptr_t if you want a pointer-sized integer.
  • You may need to be careful with structure alignments, particularly for structures being stored on disk. Any class/structure with a int64_t/uint64_t member will by default end up being 8-byte aligned on a 64-bit system. If you have such structures being shared on disk between 32-bit and 64-bit code, you will need to ensure that they are packed the same on both architectures. Most compilers offer a way to alter structure alignment. For gcc, you can use __attribute__((packed)). MSVC offers #pragma pack() and __declspec(align()).
  • Use the LL or ULL suffixes as needed to create 64-bit constants. For example:
    int64_t my_value = 0x123456789LL;    uint64_t my_mask = 3ULL << 48;
  • If you really need different code on 32-bit and 64-bit systems, use #ifdef _LP64 to choose between the code variants. (But please avoid this if possible, and keep any such changes localized.)

Preprocessor Macros

link▽Be very cautious with macros. Prefer inline functions, enums,and const variables to macros.

Macros mean that the code you see is not the same as the codethe compiler sees. This can introduce unexpected behavior,especially since macros have global scope.

Luckily, macros are not nearly as necessary in C++ as they arein C. Instead of using a macro to inline performance-criticalcode, use an inline function. Instead of using a macro tostore a constant, use a const variable. Instead ofusing a macro to "abbreviate" a long variable name, use areference. Instead of using a macro to conditionally compile code... well, don't do that at all (except, of course, for the#define guards to prevent double inclusion ofheader files). It makes testing much more difficult.

Macros can do things these other techniques cannot, and you dosee them in the codebase, especially in the lower-levellibraries. And some of their special features (likestringifying, concatenation, and so forth) are not availablethrough the language proper. But before using a macro,consider carefully whether there's a non-macro way to achievethe same result.

The following usage pattern will avoid many problems withmacros; if you use macros, follow it whenever possible:

  • Don't define macros in a .h file.
  • #define macros right before you use them, and #undef them right after.
  • Do not just #undef an existing macro before replacing it with your own; instead, pick a name that's likely to be unique.
  • Try not to use macros that expand to unbalanced C++ constructs, or at least document that behavior well.
  • Prefer not using ## to generate function/class/variable names.

0 and NULL

link▽Use 0 for integers, 0.0 for reals,NULL for pointers, and '\0' for chars.

Use 0 for integers and 0.0 for reals.This is not controversial.

For pointers (address values), there is a choice between 0and NULL. Bjarne Stroustrup prefers an unadorned0. We prefer NULL because it looks like apointer. In fact, some C++ compilers, such as gcc 4.1.0, provide specialdefinitions of NULL which enable them to give usefulwarnings, particularly in situations where sizeof(NULL)is not equal to sizeof(0).

Use '\0' for chars.This is the correct type and also makes code more readable.

sizeof

link▽Use sizeof(varname) instead ofsizeof(type) whenever possible.

Use sizeof(varname) because it will updateappropriately if the type of the variable changes.sizeof(type) may make sense in some cases,but should generally be avoided because it can fall out of sync ifthe variable's type changes.

Struct data;memset(&data, 0, sizeof(data));
memset(&data, 0, sizeof(Struct));

 

Boost

link▽Use only approved libraries from the Boost library collection.

Definition: The Boost library collection isa popular collection of peer-reviewed, free, open-source C++ libraries.

Pros: Boost code is generally very high-quality, is widely portable, and fillsmany important gaps in the C++ standard library, such as type traits,better binders, and better smart pointers. It also provides animplementation of the TR1 extension to the standard library.

Cons: Some Boost libraries encourage coding practices which can hamperreadability, such as metaprogramming and other advanced templatetechniques, and an excessively "functional" style of programming.

Decision:

In order to maintain a high level of readability for all contributorswho might read and maintain code, we only allow an approved subset ofBoost features. Currently, the following libraries are permitted:
  • Call Traits from boost/call_traits.hpp
  • Compressed Pair from boost/compressed_pair.hpp
  • Pointer Container from boost/ptr_container except serialization and wrappers for containers not in the C++03 standard (ptr_circular_buffer.hpp and ptr_unordered*)
  • Array from boost/array.hpp
  • The Boost Graph Library (BGL) from boost/graph, except serialization (adj_list_serialize.hpp) and parallel/distributed algorithms and data structures (boost/graph/parallel/* and boost/graph/distributed/*).
  • Property Map from boost/property_map, except parallel/distributed property maps (boost/property_map/parallel/*).
  • The part of Iterator that deals with defining iterators: boost/iterator/iterator_adaptor.hpp, boost/iterator/iterator_facade.hpp, and boost/function_output_iterator.hpp
We are actively considering adding other Boost features to the list, sothis rule may be relaxed in the future.

 

C++0x

link▽Use only approved libraries and language extensions from C++0x.Currently, none are approved.

Definition: C++0x is the next ISO C++ standard, currently infinalcommittee draft form. It containssignificantchanges both to the language and libraries.

Pros: We expect that C++0x will become the next standard, and eventually willbe supported by most C++ compilers. It standardizes some common C++extensions that we use already, allows shorthands for some operations,and has some safety improvements.

Cons:

The C++0x standard is substantialy more complex than its predecessor(1,300 pages versus 800 pages), and isunfamilar to many developers. The long-term effects of somefeatures on code readability and maintenance are unknown. We cannotpredict when its various features will be implemented uniformly bytools that may be of interest (gcc, icc, clang, Eclipse, etc.).

As with Boost, some C++0x extensions encouragecoding practices that hamper readability—for example by removingchecked redundancy (such as type names) that may be helpful to readers,or by encouraging template metaprogramming. Other extensionsduplicate functionality available through existingmechanisms, which may lead toconfusion and conversion costs.

 

Decision: Use only C++0x libraries and language features that have been approvedfor use. Currently, no such features are approved.Features will be approved individually as appropriate.

Naming

The most important consistency rules are those that governnaming. The style of a name immediately informs us what sort ofthing the named entity is: a type, a variable, a function, aconstant, a macro, etc., without requiring us to search for thedeclaration of that entity. The pattern-matching engine in ourbrains relies a great deal on these naming rules.

Naming rules are pretty arbitrary, butwe feel that consistency is more important than individual preferencesin this area, so regardless of whether you find them sensible or not,the rules are the rules.

General Naming Rules

link▽Function names, variable names, and filenames should bedescriptive; eschew abbreviation. Types and variables should benouns, while functions should be "command" verbs.

How to Name

Give as descriptive a name as possible, within reason. Donot worry about saving horizontal space as it is far moreimportant to make your code immediately understandable by anew reader. Examples of well-chosen names:

int num_errors;                  // Good.int num_completed_connections;   // Good.

Poorly-chosen names use ambiguous abbreviations or arbitrarycharacters that do not convey meaning:

int n;                           // Bad - meaningless.int nerr;                        // Bad - ambiguous abbreviation.int n_comp_conns;                // Bad - ambiguous abbreviation.

Type and variable names should typically be nouns: e.g.,FileOpener,num_errors.

Function names should typically be imperative (that is theyshould be commands): e.g., OpenFile(),set_num_errors(). There is an exception foraccessors, which, described more completely in Function Names, should be namedthe same as the variable they access.

 

Abbreviations

Do not use abbreviations unless they are extremely wellknown outside your project. For example:

// Good// These show proper names with no abbreviations.int num_dns_connections;  // Most people know what "DNS" stands for.int price_count_reader;   // OK, price count. Makes sense.
// Bad!// Abbreviations can be confusing or ambiguous outside a small group.int wgc_connections;  // Only your group knows what this stands for.int pc_reader;        // Lots of things can be abbreviated "pc".

Never abbreviate by leaving out letters:

int error_count;  // Good.
int error_cnt;    // Bad.

 

File Names

link▽Filenames should be all lowercase and can include underscores(_) or dashes (-). Follow theconvention that yourprojectuses. If there is no consistent local pattern to follow, prefer "_".

Examples of acceptable file names:

my_useful_class.cc
my-useful-class.cc
myusefulclass.cc
myusefulclass_test.cc // _unittest and _regtest are deprecated.

C++ files should end in .cc and header filesshould end in .h.

Do not use filenames that already existin /usr/include, such as db.h.

In general, make your filenames very specific. For example,use http_server_logs.h ratherthan logs.h. A very common case is to have apair of files called, e.g., foo_bar.hand foo_bar.cc, defining a classcalled FooBar.

Inline functions must be in a .h file. If yourinline functions are very short, they should go directly into your.h file. However, if your inline functionsinclude a lot of code, they may go into a third file thatends in -inl.h. In a class with a lot of inlinecode, your class could have three files:

url_table.h      // The class declaration.url_table.cc     // The class definition.url_table-inl.h  // Inline functions that include lots of code.

See also the section -inl.h Files

Type Names

link▽Type names start with a capital letter and have a capitalletter for each new word, with no underscores:MyExcitingClass, MyExcitingEnum.

The names of all types — classes, structs, typedefs, and enums— have the same naming convention. Type names should startwith a capital letter and have a capital letter for each newword. No underscores. For example:

// classes and structsclass UrlTable { ...class UrlTableTester { ...struct UrlTableProperties { ...// typedefstypedef hash_map PropertiesMap;// enumsenum UrlTableErrors { ...

Variable Names

link▽Variable names are all lowercase, with underscores betweenwords. Class member variables have trailing underscores. Forinstance: my_exciting_local_variable,my_exciting_member_variable_.

Common Variable names

For example:

string table_name;  // OK - uses underscore.string tablename;   // OK - all lowercase.
string tableName;   // Bad - mixed case.

 

Class Data Members

Data members (also called instance variables or membervariables) are lowercase with optional underscores likeregular variable names, but always end with a trailingunderscore.

string table_name_;  // OK - underscore at end.string tablename_;   // OK.

 

Struct Variables

Data members in structs should be named like regularvariables without the trailing underscores that data membersin classes have.

struct UrlTableProperties {string name;int num_entries;}

See Structs vs. Classes for adiscussion of when to use a struct versus a class.

 

Global Variables

There are no special requirements for global variables,which should be rare in any case, but if you use one,consider prefixing it with g_ or some othermarker to easily distinguish it from local variables.

 

Constant Names

link▽Use a k followed by mixed case:kDaysInAWeek.

All compile-time constants, whether they are declared locally,globally, or as part of a class, follow a slightly differentnaming convention from other variables. Use a kfollowed by words with uppercase first letters:

const int kDaysInAWeek = 7;

Function Names

link▽Regular functions have mixed case; accessors and mutators matchthe name of the variable: MyExcitingFunction(),MyExcitingMethod(),my_exciting_member_variable(),set_my_exciting_member_variable().

Regular Functions

Functions should start with a capital letter and have acapital letter for each new word. No underscores.

If your function crashes upon an error, you should append OrDie tothe function name. This only applies to functions which could beused by production code and to errors that are reasonablylikely to occur during normal operation.

AddTableEntry()DeleteUrl()OpenFileOrDie()

 

Accessors and Mutators

Accessors and mutators (get and set functions) should matchthe name of the variable they are getting and setting. Thisshows an excerpt of a class whose instance variable isnum_entries_.

class MyClass {public:...int num_entries() const { return num_entries_; }void set_num_entries(int num_entries) { num_entries_ = num_entries; }private:int num_entries_;};

You may also use lowercase letters for other very shortinlined functions. For example if a function were so cheapyou would not cache the value if you were calling it in aloop, then lowercase naming would be acceptable.

 

Namespace Names

link▽Namespace names are all lower-case, and based on project names andpossibly their directory structure:google_awesome_project.

See Namespaces for a discussion ofnamespaces and how to name them.

Enumerator Names

link▽Enumerators should be named either likeconstants or likemacros: either kEnumNameor ENUM_NAME.

Preferably, the individual enumerators should be named likeconstants. However, it is alsoacceptable to name them like macros. The enumeration name,UrlTableErrors (andAlternateUrlTableErrors), is a type, andtherefore mixed case.

enum UrlTableErrors {kOK = 0,kErrorOutOfMemory,kErrorMalformedInput,};enum AlternateUrlTableErrors {OK = 0,OUT_OF_MEMORY = 1,MALFORMED_INPUT = 2,};

Until January 2009, the style was to name enum values likemacros. This caused problems withname collisions between enum values and macros. Hence, thechange to prefer constant-style naming was put in place. Newcode should prefer constant-style naming if possible.However, there is no reason to change old code to useconstant-style names, unless the old names are actuallycausing a compile-time problem.

Macro Names

link▽You're not really going to definea macro, are you? If you do, they're like this:MY_MACRO_THAT_SCARES_SMALL_CHILDREN.

Please see the description ofmacros; in general macros should not be used.However, if they are absolutely needed, then they should benamed with all capitals and underscores.

#define ROUND(x) ...#define PI_ROUNDED 3.0

Exceptions to Naming Rules

link▽If you are naming something that is analogous to an existing Cor C++ entity then you can follow the existing naming conventionscheme.

bigopen()
function name, follows form of open()
uint
typedef
bigpos
struct or class, follows form ofpos
sparse_hash_map
STL-like entity; follows STL naming conventions
LONGLONG_MAX
a constant, as in INT_MAX

 

Comments

Though a pain to write, comments are absolutely vital to keeping ourcode readable. The following rules describe what you shouldcomment and where. But remember: while comments are veryimportant, the best code is self-documenting. Giving sensiblenames to types and variables is much better than using obscurenames that you must then explain through comments.

When writing your comments, write for your audience: the nextcontributorwho will need to understand your code. Be generous — the nextone may be you!

Comment Style

link▽Use either the // or /* */ syntax, as longas you are consistent.

You can use either the // or the /* */syntax; however, // is much more common.Be consistent with how you comment and what style you use where.

File Comments

link▽Start each file with a copyright notice, followed by adescription of the contents of the file.

Legal Notice and Author Line

Every file should contain the following items, in order:

  • a copyright statement (for example, Copyright 2008 Google Inc.)
  • a license boilerplate. Choose the appropriate boilerplate for the license used by the project (for example, Apache 2.0, BSD, LGPL, GPL)
  • an author line to identify the original author of the file

 

If you make significant changes to a file that someone elseoriginally wrote, add yourself to the author line. This canbe very helpful when anothercontributorhas questions about the file and needs to know whom to contactabout it.

 

File Contents

Every file should have a comment at the top, below the copyrightnotice and author line, that describes the contents of the file.

Generally a .h file will describe the classesthat are declared in the file with an overview of what theyare for and how they are used. A .cc fileshould contain more information about implementation detailsor discussions of tricky algorithms. If you feel theimplementation details or a discussion of the algorithmswould be useful for someone reading the .h,feel free to put it there instead, but mention in the.cc that the documentation is in the.h file.

Do not duplicate comments in both the .h andthe .cc. Duplicated comments diverge.

 

Class Comments

link▽Every class definition should have an accompanying comment thatdescribes what it is for and how it should be used.
// Iterates over the contents of a GargantuanTable.  Sample usage://    GargantuanTableIterator* iter = table->NewIterator();//    for (iter->Seek("foo"); !iter->done(); iter->Next()) {//      process(iter->key(), iter->value());//    }//    delete iter;class GargantuanTableIterator {...};

If you have already described a class in detail in thecomments at the top of your file feel free to simply state"See comment at top of file for a complete description", butbe sure to have some sort of comment.

Document the synchronization assumptions the class makes, ifany. If an instance of the class can be accessed by multiplethreads, take extra care to document the rules and invariantssurrounding multithreaded use.

Function Comments

link▽Declaration comments describe use of the function; comments atthe definition of a function describe operation.

Function Declarations

Every function declaration should have comments immediatelypreceding it that describe what the function does and how touse it. These comments should be descriptive ("Opens thefile") rather than imperative ("Open the file"); the commentdescribes the function, it does not tell the function whatto do. In general, these comments do not describe how thefunction performs its task. Instead, that should be left tocomments in the function definition.

Types of things to mention in comments at the functiondeclaration:

  • What the inputs and outputs are.
  • For class member functions: whether the object remembers reference arguments beyond the duration of the method call, and whether it will free them or not.
  • If the function allocates memory that the caller must free.
  • Whether any of the arguments can be NULL.
  • If there are any performance implications of how a function is used.
  • If the function is re-entrant. What are its synchronization assumptions?

Here is an example:

// Returns an iterator for this table.  It is the client's// responsibility to delete the iterator when it is done with it,// and it must not use the iterator once the GargantuanTable object// on which the iterator was created has been deleted.//// The iterator is initially positioned at the beginning of the table.//// This method is equivalent to://    Iterator* iter = table->NewIterator();//    iter->Seek("");//    return iter;// If you are going to immediately seek to another place in the// returned iterator, it will be faster to use NewIterator()// and avoid the extra seek.Iterator* GetIterator() const;

However, do not be unnecessarily verbose or state thecompletely obvious. Notice below that it is not necessaryto say "returns false otherwise" because this is implied.

// Returns true if the table cannot hold any more entries.bool IsTableFull();

When commenting constructors and destructors, remember thatthe person reading your code knows what constructors anddestructors are for, so comments that just say something like"destroys this object" are not useful. Document whatconstructors do with their arguments (for example, if theytake ownership of pointers), and what cleanup the destructordoes. If this is trivial, just skip the comment. It isquite common for destructors not to have a header comment.

 

Function Definitions

Each function definition should have a comment describingwhat the function does if there's anything tricky about how it doesits job. For example, in the definition comment you mightdescribe any coding tricks you use, give an overview of thesteps you go through, or explain why you chose to implementthe function in the way you did rather than using a viablealternative. For instance, you might mention why it mustacquire a lock for the first half of the function but why itis not needed for the second half.

Note you should not just repeat the comments givenwith the function declaration, in the .h file orwherever. It's okay to recapitulate briefly what the functiondoes, but the focus of the comments should be on how it does it.

 

Variable Comments

link▽In general the actual name of the variable should be descriptiveenough to give a good idea of what the variable is used for. Incertain cases, more comments are required.

Class Data Members

Each class data member (also called an instance variable ormember variable) should have a comment describing what it isused for. If the variable can take sentinel values withspecial meanings, such as NULL or -1, document this.For example:

private:// Keeps track of the total number of entries in the table.// Used to ensure we do not go over the limit. -1 means// that we don't yet know how many entries the table has.int num_total_entries_;

 

Global Variables

As with data members, all global variables should have acomment describing what they are and what they are used for.For example:

// The total number of tests cases that we run through in this regression test.const int kNumTestCases = 6;

 

Implementation Comments

link▽In your implementation you should have comments in tricky,non-obvious, interesting, or important parts of your code.

Class Data Members

Tricky or complicated code blocks should have commentsbefore them. Example:

// Divide result by two, taking into account that x// contains the carry from the add.for (int i = 0; i < result->size(); i++) {x = (x << 8) + (*result)[i];(*result)[i] = x >> 1;x &= 1;}

 

Line Comments

Also, lines that are non-obvious should get a comment at theend of the line. These end-of-line comments should beseparated from the code by 2 spaces. Example:

// If we have enough memory, mmap the data portion too.mmap_budget = max(0, mmap_budget - index_->length());if (mmap_budget >= data_size_ && !MmapData(mmap_chunk_bytes, mlock))return;  // Error already logged.

Note that there are both comments that describe what thecode is doing, and comments that mention that an error hasalready been logged when the function returns.

If you have several comments on subsequent lines, it canoften be more readable to line them up:

DoSomething();                  // Comment here so the comments line up.DoSomethingElseThatIsLonger();  // Comment here so there are two spaces between// the code and the comment.{ // One space before comment when opening a new scope is allowed,// thus the comment lines up with the following comments and code.DoSomethingElse();  // Two spaces before line comments normally.}

 

NULL, true/false, 1, 2, 3...

When you pass in NULL, boolean, or literal integervalues to functions, you should consider adding a comment aboutwhat they are, or make your code self-documenting by usingconstants. For example, compare:

bool success = CalculateSomething(interesting_value,10,false,NULL);  // What are these arguments??

versus:

bool success = CalculateSomething(interesting_value,10,     // Default base value.false,  // Not the first time we're calling this.NULL);  // No callback.

Or alternatively, constants or self-describing variables:

const int kDefaultBaseValue = 10;const bool kFirstTimeCalling = false;Callback *null_callback = NULL;bool success = CalculateSomething(interesting_value,kDefaultBaseValue,kFirstTimeCalling,null_callback);

 

Don'ts

Note that you should never describe the codeitself. Assume that the person reading the code knows C++better than you do, even though he or she does not know whatyou are trying to do:

// Now go through the b array and make sure that if i occurs,// the next element is i+1....        // Geez.  What a useless comment.

 

Punctuation, Spelling and Grammar

link▽Pay attention to punctuation, spelling, and grammar; it iseasier to read well-written comments than badly written ones.

Comments should usually be written as completesentences with proper capitalization and periods at the end.Shorter comments, such as comments at the end of a line ofcode, can sometimes be less formal, but you should beconsistent with your style. Complete sentences are morereadable, and they provide some assurance that the comment iscomplete and not an unfinished thought.

Although it can be frustrating to have a code reviewer pointout that you are using a comma when you should be using asemicolon, it is very important that source code maintain ahigh level of clarity and readability. Proper punctuation,spelling, and grammar help with that goal.

TODO Comments

link▽Use TODO comments for code that is temporary, ashort-term solution, or good-enough but not perfect.

TODOs should include the string TODO inall caps, followed by thename, e-mail address, or otheridentifierof the person who can best provide context about the problemreferenced by the TODO. A colon is optional. The mainpurpose is to have a consistent TODO format that can besearched to find the person who can provide more details upon request.A TODO is not a commitment that the person referencedwill fix the problem. Thus when you create a TODO, it isalmost always yournamethat is given.

// TODO(kl@gmail.com): Use a "*" here for concatenation operator.// TODO(Zeke) change this to use relations.

If your TODO is of the form "At a future date dosomething" make sure that you either include a very specificdate ("Fix by November 2005") or a very specific event("Remove this code when all clients can handle XML responses.").

Deprecation Comments

link▽Mark deprecated interface points with DEPRECATED comments.

You can mark an interface as deprecated by writing a comment containingthe word DEPRECATED in all caps. The comment goes eitherbefore the declaration of the interface or on the same line as thedeclaration.

After the word DEPRECATED, write your name, e-mail address,or other identifier in parentheses.

A deprecation comment must include simple, clear directions for people tofix their callsites. In C++, you can implement a deprecated function asan inline function that calls the new interface point.

Marking an interface point DEPRECATED will not magicallycause any callsites to change. If you want people to actually stop usingthe deprecated facility, you will have to fix the callsites yourself orrecruit a crew to help you.

New code should not contain calls to deprecated interface points. Usethe new interface point instead. If you cannot understand thedirections, find the person who created the deprecation and ask them forhelp using the new interface point.

Formatting

Coding style and formatting are pretty arbitrary, but aprojectis much easier to follow if everyone uses the same style. Individualsmay not agree with every aspect of the formatting rules, and some ofthe rules may take some getting used to, but it is important that allproject contributorsfollow the style rules so thattheycan all read and understand everyone's code easily.

To help you format code correctly, we've created a settingsfile for emacs.

Line Length

link▽Each line of text in your code should be at most 80 characterslong.

We recognize that this rule is controversial, but so much existingcode already adheres to it, and we feel that consistency isimportant.

Pros: Those who favorthis rule arguethat it is rude to force them to resize their windows and thereis no need for anything longer. Some folks are used to havingseveral code windows side-by-side, and thus don't have room towiden their windows in any case. People set up their workenvironment assuming a particular maximum window width, and 80columns has been the traditional standard. Why change it?

Cons: Proponents of change argue that a wider line can make codemore readable. The 80-column limit is an hideboundthrowback to 1960s mainframes;modern equipment haswide screens that can easily show longer lines.

Decision:

80 characters is the maximum.

Exception: if a comment line contains an example command ora literal URL longer than 80 characters, that line may belonger than 80 characters for ease of cut and paste.

Exception: an #include statement with a longpath may exceed 80 columns. Try to avoid situations where thisbecomes necessary.

Exception: you needn't be concerned aboutheader guardsthat exceed the maximum length.

 

Non-ASCII Characters

link▽Non-ASCII characters should be rare, and must use UTF-8 formatting.

You shouldn't hard-code user-facing text in source, even English,so use of non-ASCII characters should be rare. However, in certaincases it is appropriate to include such words in your code. Forexample, if your code parses data files from foreign sources,it may be appropriate to hard-code the non-ASCII string(s) used inthose data files as delimiters. More commonly, unittest code(which does notneed to be localized) might contain non-ASCII strings. In suchcases, you should use UTF-8, since that isan encoding understood by most tools ableto handle more than just ASCII.Hex encoding is also OK, and encouraged where it enhancesreadability — for example, "\xEF\xBB\xBF" is theUnicode zero-width no-break space character, which would beinvisible if included in the source as straight UTF-8.

Spaces vs. Tabs

link▽Use only spaces, and indent 2 spaces at a time.

We use spaces for indentation. Do not use tabs in your code.You should set your editor to emit spaces when you hit the tabkey.

Function Declarations and Definitions

link▽Return type on the same line as function name, parameters on thesame line if they fit.

Functions look like this:

ReturnType ClassName::FunctionName(Type par_name1, Type par_name2) {DoSomething();...}

If you have too much text to fit on one line:

ReturnType ClassName::ReallyLongFunctionName(Type par_name1, Type par_name2,Type par_name3) {DoSomething();...}

or if you cannot fit even the first parameter:

ReturnType LongClassName::ReallyReallyReallyLongFunctionName(Type par_name1,  // 4 space indentType par_name2,Type par_name3) {DoSomething();  // 2 space indent...}

Some points to note:

  • The return type is always on the same line as the function name.
  • The open parenthesis is always on the same line as the function name.
  • There is never a space between the function name and the open parenthesis.
  • There is never a space between the parentheses and the parameters.
  • The open curly brace is always at the end of the same line as the last parameter.
  • The close curly brace is either on the last line by itself or (if other style rules permit) on the same line as the open curly brace.
  • There should be a space between the close parenthesis and the open curly brace.
  • All parameters should be named, with identical names in the declaration and implementation.
  • All parameters should be aligned if possible.
  • Default indentation is 2 spaces.
  • Wrapped parameters have a 4 space indent.

If your function is const, the constkeyword should be on the same line as the last parameter:

// Everything in this function signature fits on a single lineReturnType FunctionName(Type par) const {...}// This function signature requires multiple lines, but// the const keyword is on the line with the last parameter.ReturnType ReallyLongFunctionName(Type par1,Type par2) const {...}

If some parameters are unused, comment out the variable name in thefunction definition:

// Always have named parameters in interfaces.class Shape {public:virtual void Rotate(double radians) = 0;}// Always have named parameters in the declaration.class Circle : public Shape {public:virtual void Rotate(double radians);}// Comment out unused named parameters in definitions.void Circle::Rotate(double /*radians*/) {}
// Bad - if someone wants to implement later, it's not clear what the// variable means.void Circle::Rotate(double) {}

Function Calls

link▽On one line if it fits; otherwise, wrap arguments at theparenthesis.

Function calls have the following format:

bool retval = DoSomething(argument1, argument2, argument3);

If the arguments do not all fit on one line, they should bebroken up onto multiple lines, with each subsequent linealigned with the first argument. Do not add spaces after theopen paren or before the close paren:

bool retval = DoSomething(averyveryveryverylongargument1,argument2, argument3);

If the function has many arguments, consider having one perline if this makes the code more readable:

bool retval = DoSomething(argument1,argument2,argument3,argument4);

If the function signature is so long that it cannot fit withinthe maximum line length, you mayplace all arguments on subsequent lines:

if (...) {......if (...) {DoSomethingThatRequiresALongFunctionName(very_long_argument1,  // 4 space indentargument2,argument3,argument4);}

Conditionals

link▽Prefer no spaces inside parentheses. The elsekeyword belongs on a new line.

There are two acceptable formats for a basic conditionalstatement. One includes spaces between the parentheses and thecondition, and one does not.

The most common form is without spaces. Either is fine, butbe consistent. If you are modifying a file, use theformat that is already present. If you are writing new code,use the format that the other files in that directory orproject use. If in doubt and you have no personal preference,do not add the spaces.

if (condition) {  // no spaces inside parentheses...  // 2 space indent.} else {  // The else goes on the same line as the closing brace....}

If you prefer you may add spaces inside theparentheses:

if ( condition ) {  // spaces inside parentheses - rare...  // 2 space indent.} else {  // The else goes on the same line as the closing brace....}

Note that in all cases you must have a space between theif and the open parenthesis. You must also havea space between the close parenthesis and the curly brace, ifyou're using one.

if(condition)     // Bad - space missing after IF.if (condition){   // Bad - space missing before {.if(condition){    // Doubly bad.
if (condition) {  // Good - proper space after IF and before {.

Short conditional statements may be written on one line ifthis enhances readability. You may use this only when theline is brief and the statement does not use theelse clause.

if (x == kFoo) return new Foo();if (x == kBar) return new Bar();

This is not allowed when the if statement has anelse:

// Not allowed - IF statement on one line when there is an ELSE clauseif (x) DoThis();else DoThat();

In general, curly braces are not required for single-linestatements, but they are allowed if you like them;conditional or loop statements with complex conditions orstatements may be more readable with curly braces. Someprojectsrequire that an if must always always have anaccompanying brace.

if (condition)DoSomething();  // 2 space indent.if (condition) {DoSomething();  // 2 space indent.}

However, if one part of an if-elsestatement uses curly braces, the other part must too:

// Not allowed - curly on IF but not ELSEif (condition) {foo;} elsebar;// Not allowed - curly on ELSE but not IFif (condition)foo;else {bar;}
// Curly braces around both IF and ELSE required because// one of the clauses used braces.if (condition) {foo;} else {bar;}

Loops and Switch Statements

link▽Switch statements may use braces for blocks. Empty loop bodies should use{} or continue.

case blocks in switch statements can havecurly braces or not, depending on your preference. If you doinclude curly braces they should be placed as shown below.

If not conditional on an enumerated value, switch statementsshould always have a default case (in the case ofan enumerated value, the compiler will warn you if any valuesare not handled). If the default case should never execute,simplyassert:

switch (var) {case 0: {  // 2 space indent...      // 4 space indentbreak;}case 1: {...break;}default: {assert(false);}}

Empty loop bodies should use {} orcontinue, but not a single semicolon.

while (condition) {// Repeat test until it returns false.}for (int i = 0; i < kSomeNumber; ++i) {}  // Good - empty body.while (condition) continue;  // Good - continue indicates no logic.
while (condition);  // Bad - looks like part of do/while loop.

Pointer and Reference Expressions

link▽No spaces around period or arrow. Pointer operators do not havetrailing spaces.

The following are examples of correctly-formatted pointer andreference expressions:

x = *p;p = &x;x = r.y;x = r->y;

Note that:

  • There are no spaces around the period or arrow when accessing a member.
  • Pointer operators have no space after the * or &.

When declaring a pointer variable or argument, you may placethe asterisk adjacent to either the type or to the variablename:

// These are fine, space preceding.char *c;const string &str;// These are fine, space following.char* c;    // but remember to do "char* c, *d, *e, ...;"!const string& str;
char * c;  // Bad - spaces on both sides of *const string & str;  // Bad - spaces on both sides of &

You should do this consistently within a singlefile,so, when modifying an existing file, use the style in thatfile.

Boolean Expressions

link▽When you have a boolean expression that is longer than the standard line length, be consistent inhow you break up the lines.

In this example, the logical AND operator is always at the endof the lines:

if (this_one_thing > this_other_thing &&a_third_thing == a_fourth_thing &&yet_another && last_one) {...}

Note that when the code wraps in this example, both ofthe && logical AND operators are at theend of the line. This is more common in Google code, thoughwrapping all operators at the beginning of the line is alsoallowed. Feel free to insert extra parentheses judiciously,because they can be very helpful in increasing readabilitywhen used appropriately. Also note that you should always use thepunctuation operators, such as && and~, rather than the word operators, such as andand compl.

Return Values

link▽Do not needlessly surround the return expression withparentheses.

Use parentheses in return expr; only where you would usethem in x = expr;.

return result;                  // No parentheses in the simple case.return (some_long_condition &&  // Parentheses ok to make a complexanother_condition);     //     expression more readable.
return (value);                // You wouldn't write var = (value);return(result);                // return is not a function!

Variable and Array Initialization

link▽Your choice of = or ().

You may choose between = and (); thefollowing are all correct:

int x = 3;int x(3);string name("Some Name");string name = "Some Name";

Preprocessor Directives

link▽The hash mark that starts a preprocessor directive shouldalways be at the beginning of the line.

Even when preprocessor directives are within the body ofindented code, the directives should start at the beginning ofthe line.

// Good - directives at beginning of lineif (lopsided_score) {#if DISASTER_PENDING      // Correct -- Starts at beginning of lineDropEverything();# if NOTIFY               // OK but not required -- Spaces after #NotifyClient();# endif#endifBackToNormal();}
// Bad - indented directivesif (lopsided_score) {#if DISASTER_PENDING  // Wrong!  The "#if" should be at beginning of lineDropEverything();#endif                // Wrong!  Do not indent "#endif"BackToNormal();}

Class Format

link▽Sections in public, protected andprivate order, each indented one space.

The basic format for a class declaration (lacking thecomments, see Class Comments fora discussion of what comments are needed) is:

class MyClass : public OtherClass {public:      // Note the 1 space indent!MyClass();  // Regular 2 space indent.explicit MyClass(int var);~MyClass() {}void SomeFunction();void SomeFunctionThatDoesNothing() {}void set_some_var(int var) { some_var_ = var; }int some_var() const { return some_var_; }private:bool SomeInternalFunction();int some_var_;int some_other_var_;DISALLOW_COPY_AND_ASSIGN(MyClass);};

Things to note:

  • Any base class name should be on the same line as the subclass name, subject to the 80-column limit.
  • The public:, protected:, and private: keywords should be indented one space.
  • Except for the first instance, these keywords should be preceded by a blank line. This rule is optional in small classes.
  • Do not leave a blank line after these keywords.
  • The public section should be first, followed by the protected and finally the private section.
  • See Declaration Order for rules on ordering declarations within each of these sections.

Constructor Initializer Lists

link▽Constructor initializer lists can be all on one line or withsubsequent lines indented four spaces.

There are two acceptable formats for initializer lists:

// When it all fits on one line:MyClass::MyClass(int var) : some_var_(var), some_other_var_(var + 1) {}

or

// When it requires multiple lines, indent 4 spaces, putting the colon on// the first initializer line:MyClass::MyClass(int var): some_var_(var),             // 4 space indentsome_other_var_(var + 1) {  // lined up...DoSomething();...}

Namespace Formatting

link▽The contents of namespaces are not indented.

Namespaces do not add an extra level ofindentation. For example, use:

namespace {void foo() {  // Correct.  No extra indentation within namespace....}}  // namespace

Do not indent within a namespace:

namespace {// Wrong.  Indented when it should not be.void foo() {...}}  // namespace

When declaring nested namespaces, put each namespace on its own line.

namespace foo {namespace bar {

Horizontal Whitespace

link▽Use of horizontal whitespace depends on location. Never put trailingwhitespace at the end of a line.

General

void f(bool b) {  // Open braces should always have a space before them....int i = 0;  // Semicolons usually have no space before them.int x[] = { 0 };  // Spaces inside braces for array initialization areint x[] = {0};    // optional.  If you use them, put them on both sides!// Spaces around the colon in inheritance and initializer lists.class Foo : public Bar {public:// For inline function implementations, put spaces between the braces// and the implementation itself.Foo(int b) : Bar(), baz_(b) {}  // No spaces inside empty braces.void Reset() { baz_ = 0; }  // Spaces separating braces from implementation....

Adding trailing whitespace can cause extra work for others editingthe same file, when they merge, as can removing existing trailingwhitespace. So: Don't introduce trailing whitespace. Remove itif you're already changing that line, or do it in a separateclean-upoperation (preferably when no-one elseis working on the file).

 

Loops and Conditionals

if (b) {          // Space after the keyword in conditions and loops.} else {          // Spaces around else.}while (test) {}   // There is usually no space inside parentheses.switch (i) {for (int i = 0; i < 5; ++i) {switch ( i ) {    // Loops and conditions may have spaces insideif ( test ) {     // parentheses, but this is rare.  Be consistent.for ( int i = 0; i < 5; ++i ) {for ( ; i < 5 ; ++i) {  // For loops always have a space after the...                   // semicolon, and may have a space before the// semicolon.switch (i) {case 1:         // No space before colon in a switch case....case 2: break;  // Use a space after a colon if there's code after it.

 

Operators

x = 0;              // Assignment operators always have spaces around// them.x = -5;             // No spaces separating unary operators and their++x;                // arguments.if (x && !y)...v = w * x + y / z;  // Binary operators usually have spaces around them,v = w*x + y/z;      // but it's okay to remove spaces around factors.v = w * (x + z);    // Parentheses should have no spaces inside them.

 

Templates and Casts

vector x;           // No spaces inside the angley = static_cast(x);  // brackets (< and >), before// <, or between >( in a cast.vector x;           // Spaces between type and pointer are// okay, but be consistent.set > x;       // C++ requires a space in > >.set< list > x;      // You may optionally use// symmetric spacing in < <.

 

Vertical Whitespace

link▽Minimize use of vertical whitespace.

This is more a principle than a rule: don't use blank lineswhen you don't have to. In particular, don't put more thanone or two blank lines between functions, resist startingfunctions with a blank line, don't end functions with a blankline, and be discriminating with your use of blank linesinside functions.

The basic principle is: The more code that fits on one screen,the easier it is to follow and understand the control flow ofthe program. Of course, readability can suffer from codebeing too dense as well as too spread out, so use yourjudgement. But in general, minimize use of verticalwhitespace.

Some rules of thumb to help when blank lines may be useful:

  • Blank lines at the beginning or end of a function very rarely help readability.
  • Blank lines inside a chain of if-else blocks may well help readability.

Exceptions to the Rules

The coding conventions described above are mandatory. However,like all good rules, these sometimes have exceptions, which wediscuss here.

Existing Non-conformant Code

link▽You may diverge from the rules when dealing with code that does notconform to this style guide.

If you find yourself modifying code that was written tospecifications other than those presented by this guide, you mayhave to diverge from these rules in order to stay consistent withthe local conventions in that code. If you are in doubt abouthow to do this, ask the original author or the person currentlyresponsible for the code. Remember that consistencyincludes local consistency, too.

Windows Code

link▽Windows programmers have developed their own set of codingconventions, mainly derived from the conventions in Windows headersand other Microsoft code. We want to make it easy for anyone tounderstand your code, so we have a single set of guidelines foreveryone writing C++ on any platform.

It is worth reiterating a few of the guidelines that you mightforget if you are used to the prevalent Windows style:

  • Do not use Hungarian notation (for example, naming an integer iNum). Use the Google naming conventions, including the .cc extension for source files.
  • Windows defines many of its own synonyms for primitive types, such as DWORD, HANDLE, etc. It is perfectly acceptable, and encouraged, that you use these types when calling Windows API functions. Even so, keep as close as you can to the underlying C++ types. For example, use const TCHAR * instead of LPCTSTR.
  • When compiling with Microsoft Visual C++, set the compiler to warning level 3 or higher, and treat all warnings as errors.
  • Do not use #pragma once; instead use the standard Google include guards. The path in the include guards should be relative to the top of your project tree.
  • In fact, do not use any nonstandard extensions, like #pragma and __declspec, unless you absolutely must. Using __declspec(dllimport) and __declspec(dllexport) is allowed; however, you must use them through macros such as DLLIMPORT and DLLEXPORT, so that someone can easily disable the extensions if they share the code.

However, there are just a few rules that we occasionally needto break on Windows:

  • Normally we forbid the use of multiple implementation inheritance; however, it is required when using COM and some ATL/WTL classes. You may use multiple implementation inheritance to implement COM or ATL/WTL classes and interfaces.
  • Although you should not use exceptions in your own code, they are used extensively in the ATL and some STLs, including the one that comes with Visual C++. When using the ATL, you should define _ATL_NO_EXCEPTIONS to disable exceptions. You should investigate whether you can also disable exceptions in your STL, but if not, it is OK to turn on exceptions in the compiler. (Note that this is only to get the STL to compile. You should still not write exception handling code yourself.)
  • The usual way of working with precompiled headers is to include a header file at the top of each source file, typically with a name like StdAfx.h or precompile.h. To make your code easier to share with other projects, avoid including this file explicitly (except in precompile.cc), and use the /FI compiler option to include the file automatically.
  • Resource headers, which are usually named resource.h and contain only macros, do not need to conform to these style guidelines.

Parting Words

Use common sense and BE CONSISTENT.

If you are editing code, take a few minutes to look at thecode around you and determine its style. If they use spacesaround their if clauses, you should, too. Iftheir comments have little boxes of stars around them, makeyour comments have little boxes of stars around them too.

The point of having style guidelines is to have a commonvocabulary of coding so people can concentrate on what you aresaying, rather than on how you are saying it. We presentglobal style rules here so people know the vocabulary. Butlocal style is also important. If code you add to a filelooks drastically different from the existing code around it,the discontinuity throws readers out of their rhythm when theygo to read it. Try to avoid this.

OK, enough writing about writing code; the code itself is muchmore interesting. Have fun!


Revision 3.188

Benjy Weinberger
Craig Silverstein
Gregory Eitzmann
Mark Mentovai
Tashana Landray