From 7b24563e08b7e6a6477eed22bca2eb4e6ac093fa Mon Sep 17 00:00:00 2001
From: "mark@chromium.org"
Date: Wed, 25 Sep 2013 21:16:00 +0000
Subject: [PATCH] Update C++ style guide to 3.274: - Change formatting rules
of braced initializers. - Permit use of constexpr and allow constexpr global
variables. - Allow all C++11 features except for those that are specifically
banned. - Fix/add C99 format specifiers for ptrdiff_t and ssize_t. - Add
lambda expressions to the list of explicitly banned C++11 features. - Relax
"return type is always on the same line as the function name" rule. - Allow
unique_ptr, discourage ownership transfer. Allow noncopyable std::move. -
Allow system-specific includes after other includes. - Add
boost/math/distributions to the set of permitted Boost libraries.
Update Objective-C style guide to 2.59:
- Use instancetype as return type for example init methods.
- Remove invalid +stringWithInt: call.
- Remove reference to pre-Objective-C 2.0 declaration requirements.
- Remove reference to Objective-C exception macros.
- Remove reference to informal protocols as an alternative to optional methods.
- Class headers should include comments documenting non-trivial interfaces.
- Don't specify that blocks are preferable to methods as callbacks.
- Specify "strong" and "weak" as comments for non-Objective-C pointers.
- Replace improper reference to ownership of a retained object.
- Clarify some aspects of method ordering rules.
- Prefixes are required for shared code and optional for applications.
- Clarify that nil pointers are safe as receivers, not necessarily parameters.
- Clarify that delegate pointers should typically be zeroing weak pointers.
- Allow a 100-column limit, except for projects that choose to use 80.
Update Python style guide to 2.59:
- Add more examples of bad code to the default arguments section.
- Allow ''' when ' is used as the single quote within a file.
- Remove references to pychecker. Recommend pylint.
- Add more examples to the indentation section.
Update JavaScript style guide to 2.93:
- Add @nocompile.
- Fix a few typos.
- When wrapping lines, indent more deeply for child expressions.
- Document that @const can be used on a constructor.
- Update eval section to discourage using eval for RPC.
- Update an example to avoid encouraging using numbers as booleans.
- Allow for no indentation of @desc jsdoc tags.
- Add @public discussion.
Update shell style guide to 1.26:
- Add a section on style for case statements.
Update Common Lisp style guide to 1.23:
- fare-matcher was superseded by optima.
- Clarify wording regarding DYNAMIC-EXTENT.
---
cppguide.xml | 804 +++++++++++++++++++++++++++++++++-----------
javascriptguide.xml | 231 ++++++++-----
lispguide.xml | 69 ++--
objcguide.xml | 232 +++++--------
pyguide.html | 154 ++++++---
shell.xml | 75 ++++-
6 files changed, 1036 insertions(+), 529 deletions(-)
diff --git a/cppguide.xml b/cppguide.xml
index a0c2abf..9c381f5 100644
--- a/cppguide.xml
+++ b/cppguide.xml
@@ -4,7 +4,7 @@
-Revision 3.260
+Revision 3.274
+ Exception: sometimes, system-specific code needs conditional includes.
+ Such code can put conditional includes after other includes.
+ Of course, keep your system-specific code small and localized.
+ Example:
+
project2::Foo
are now distinct symbols that
do not collide.
+ + Inline namespaces automatically place their names in the + enclosing scope. Consider the following snippet, for example: +
+
+ The expressions X::Y::foo()
and
+ X::foo()
are interchangeable. Inline namespaces
+ are primarily intended for ABI compatibility across versions.
+
@@ -452,6 +484,12 @@ Tashana Landray additional (hierarchical) axis of naming, in addition to the (also hierarchical) name axis provided by classes.
++ Inline namespaces, in particular, can be confusing because + names aren't actually restricted to the namespace where they + are declared. They are only useful as part of some larger + versioning policy. +
Use of unnamed namespaces in header files can easily cause violations of the C++ One Definition Rule (ODR). @@ -608,6 +646,8 @@ Tashana Landray goal of keeping public APIs as small as possible.
+constexpr
:
+ they have no dynamic initialization or destruction.
@@ -805,14 +847,30 @@ Tashana Landray itself depend on any other globals.
- Likewise, the order in which destructors are called is defined to be the
- reverse of the order in which the constructors were called. Since
- constructor order is indeterminate, so is destructor order.
- For example, at program-end time a static variable might have
- been 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 that
- contains a reference to that string.
+ Likewise, global and static variables are destroyed when the
+ program terminates, regardless of whether the termination is by
+ returning from main()
or by calling
+ exit()
. The order in which destructors are called is
+ defined to be the reverse of the order in which the constructors
+ were called. Since constructor order is indeterminate, so is
+ destructor order. For example, at program-end time a static
+ variable might have been 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 that contains a
+ reference to that string.
+
+ One way to alleviate the destructor problem is to terminate the
+ program by calling quick_exit()
instead of
+ exit()
. The difference is that quick_exit()
+ does not invoke destructors and does not invoke any handlers that were
+ registered by calling atexit()
. If you have a handler that
+ needs to run when a program terminates via
+ quick_exit()
(flushing logs, for example), you can
+ register it using at_quick_exit()
. (If you have a handler
+ that needs to run at both exit()
and
+ quick_exit()
, you need to register it in both places.)
As a result we only allow static variables to contain POD data. This
@@ -888,32 +946,65 @@ Tashana Landray
-
+ A user defined default constructor is used to initialize an object
+ if no initializer is provided. It can ensure that an object is
+ always in a valid and usable state as soon as it's constructed; it
+ can also ensure that an object is initially created in an obviously
+ "impossible" state, to aid debugging.
+
+ In-class member initialization ensures that a member variable will
+ be initialized appropriately without having to duplicate the
+ initialization code in multiple constructors. This can reduce bugs
+ where you add a new member variable, initialize it in one
+ constructor, and forget to put that initialization code in another
+ constructor.
+
+ Explicitly defining a default constructor is extra work for
+ you, the code writer.
+
+ In-class member initialization is potentially confusing if a member
+ variable is initialized as part of its declaration and also
+ initialized in a constructor, since the value in the constructor
+ will override the value in the declaration.
+
- If your class defines member variables and has no other
- constructors you must define a default constructor (one that
- takes no arguments). It should preferably initialize the
- object in such a way that its internal state is consistent
- and valid.
+ Use in-class member initialization for simple initializations,
+ especially when a member variable must be initialized the same way
+ in more than one constructor.
+
+ If your class defines member variables that aren't
+ initialized in-class, and if it has no other constructors,
+ you must define a default constructor (one that takes no
+ arguments). It should preferably initialize the object in
+ such a way that its internal state is consistent and valid.
The reason for this is that if you have no other
@@ -1068,6 +1159,90 @@ Tashana Landray
+ Delegating and inheriting constructors are two different features,
+ both introduced in C++11, for reducing code duplication in
+ constructors. Delegating constructors allow one of a class's
+ constructors to forward work to one of the class's other
+ constructors, using a special variant of the initialization list
+ syntax. For example:
+
+ Inheriting constructors allow a derived class to have its base
+ class's constructors available directly, just as with any of the
+ base class's other member functions, instead of having to redeclare
+ them. This is especially useful if the base has multiple
+ constructors. For example:
+
+ This is especially useful when
+ Delegating and inheriting constructors reduce verbosity
+ and boilerplate, which can improve readability.
+
+ Delegating constructors are familiar to Java programmers.
+
+ It's possible to approximate the behavior of delegating constructors
+ by using a helper function.
+
+ Inheriting constructors may be confusing if a derived class
+ introduces new member variables, since the base class constructor
+ doesn't know about them.
+
+ Use delegating and inheriting
+ constructors when they reduce boilerplate and improve
+ readability. Be cautious about inheriting
+ constructors when your derived class has new member variables.
+ Inheriting constructors may still be appropriate in that case
+ if you can use in-class member initialization for the derived
+ class's member variables.
+
+
+ Operator overloading can make code appear more intuitive because a
+ class will behave in the same way as built-in types (such as
+
+ For some template functions to work correctly, you may need to
+ define operators.
+
+ User-defined literals are a very concise notation for creating
+ objects of user-defined types.
+ new
a
- class object with no arguments. It is always called when
- calling new[]
(for arrays).
+ The default constructor is called when we new
a class
+ object with no arguments. It is always called when calling
+ new[]
(for arrays). In-class member initialization means
+ declaring a member variable using a construction like int count_
+ = 17;
or string name_{"abc"};
, as opposed to just
+ int count_;
or string name_;
.
Derived
's constructors
+ don't have to do anything more than calling Base
's
+ constructors.
+ struct
only for passive objects that carry data;
@@ -1274,21 +1449,32 @@ Tashana Landray
+
and
/
operate on the class as if it were a built-in
- type.
+ type. An overload of operator""
allows
+ the built-in literal syntax to be used to create objects of
+ class types.
int
). Overloaded operators are more playful
- names for functions that are less-colorfully named, such as
- Equals()
or Add()
. For some
- template functions to work correctly, you may need to define
- operators.
+ int
). Overloaded operators are more playful names for
+ functions that are less-colorfully named, such as
+ Equals()
or Add()
.
+ operator&
, it
@@ -1323,6 +1512,10 @@ Tashana Landray
unary operator&
at all costs, if there's
any possibility the class might be forward-declared.
+ Do not overload operator""
, i.e.
+ do not introduce user-defined literals.
+
However, there may be rare cases where you need to overload
an operator to interoperate with templates or "standard" C++
@@ -1462,55 +1655,115 @@ Tashana Landray
-
+ "Ownership" is a bookkeeping technique for managing dynamically
+ allocated memory (and other resources). The owner of a dynamically
+ allocated object is an object or function that is responsible for
+ ensuring that it is deleted when no longer needed. Ownership can
+ sometimes be shared, in which case the last owner is typically
+ responsible for deleting it. Even when ownership is not shared,
+ it can be transferred from one piece of code to another.
+
+ "Smart" pointers are classes that act like pointers, e.g. by
+ overloading the
+ If dynamic allocation is necessary, prefer to keep ownership with
+ the code that allocated it. If other code needs access to the object,
+ consider passing it a copy, or passing a pointer or reference
+ without transferring ownership. Prefer to use
+ unique_ptr
- is great, and scoped_ptr
is fine if you need to support
- older versions of C++. You should only use shared_ptr
- with a non-const referent when it is truly necessary to share ownership
- of an object (e.g. inside an STL container). You should never use
- auto_ptr
.
+ Prefer to have single, fixed owners for dynamically allocated objects.
+ Prefer to transfer ownership with smart pointers.
*
and ->
operators.
+ Some smart pointer types can be used to automate ownership
+ bookkeeping, to ensure these responsibilities are met.
+
+ std::unique_ptr
is a smart pointer type introduced
+ in C++11, which expresses exclusive ownership of a dynamically
+ allocated object; the object is deleted when the
+ std::unique_ptr
goes out of scope. It cannot be copied,
+ but can be moved to represent ownership transfer.
+ shared_ptr
is a smart pointer type which expresses
+ shared ownership of a dynamically allocated object.
+ shared_ptr
s can be copied; ownership of the object is
+ shared among all copies, and the object is deleted when the last
+ shared_ptr
is destroyed.
+
+
auto_ptr
) can be nonobvious and confusing. The
- exception-safety benefits of smart pointers are not decisive, since
- we do not allow exceptions.
+
+
std::unique_ptr
expresses ownership transfer
+ using C++11's move semantics, which are
+ generally forbidden in Google
+ code, and may confuse some programmers.
-
+ unique_ptr
scoped_ptr
unique_ptr
unless C++03 compatibility is
- required.auto_ptr
unique_ptr
instead, if possible.std::unique_ptr
to make ownership transfer explicit.
+ For example:
+ shared_ptr
shared_ptr<const
- T>
). Reference-counted pointers with non-const referents
- can occasionally be the best design, but try to rewrite with single
- owners where possible.
-
+ Do not design your code to use shared ownership without a very good
+ reason. One such reason is to avoid expensive copy operations,
+ but you should only do this if the performance benefits are
+ significant, and the underlying object is immutable (i.e.
+ shared_ptr<const Foo>
). If you do use shared
+ ownership, prefer to use shared_ptr
.
+
+
+ Do not use scoped_ptr
in new code unless you need to be
+ compatible with older versions of C++. Never use
+ linked_ptr
or std::auto_ptr
. In all three
+ cases, use std::unique_ptr
instead.
+
std::forward
,
+ std::move_iterator
, or std::move_if_noexcept
.
+ Use the single-argument form of std::move
only with
+ non-copyable arguments.
+ void f(string&& s);
declares a
+ function whose argument is an rvalue reference to a string.
+ v1
is a vector<string>
,
+ for example, then auto v2(std::move(v1))
will probably
+ just result in some simple pointer manipulation instead of copying a
+ large amount of data. In some cases this can result in a major
+ performance improvement.
+ std::move
is necessary to make effective use of some
+ standard-library types, such as std::unique_ptr
.
+
+ Do not use rvalue references, and do not use the
+ std::forward
or std::move_if_noexcept
+ utility functions (which are essentially just casts to rvalue
+ reference types), or std::move_iterator
. Use
+ single-argument std::move
only with objects that are
+ not copyable (e.g. std::unique_ptr
), or in templated
+ code with objects that might not be copyable.
+
+ This prohibition also applies to the exception-related
+ features added in C++11, such as noexcept
,
+ std::exception_ptr
, and
+ std::nested_exception
.
+
There is an exception to this
rule (no pun intended) for Windows code.
@@ -2179,6 +2507,8 @@ Tashana Landray
+
- For pointers (address values), there is a choice between const
whenever it makes sense.
+ With C++11,
+ constexpr
is a better choice for some uses of const.
constexpr
+ to define true constants or to ensure constant initialization.
+ constexpr
+ to indicate the variables are true constants,
+ i.e. fixed at compilation/link time.
+ Some functions and constructors can be declared constexpr
+ which enables them to be used
+ in defining a constexpr
variable.
+ constexpr
enables
+ definition of constants with floating-point expressions
+ rather than just literals;
+ definition of constants of user-defined types; and
+ definition of constants with function calls.
+ constexpr
definitions enable a more robust
+ specification of the constant parts of an interface.
+ Use constexpr
to specify true constants
+ and the functions that support their definitions.
+ Avoid complexifying function definitions to enable
+ their use with constexpr
.
+ Do not use constexpr
to force inlining.
+ %u
- %"PRIuS"
,
%"PRIxS"
C99 specifies
+ %zu
+ C99 specifies
%zu
@@ -2587,8 +2962,8 @@ Tashana Landray
ptrdiff_t
%d
- %"PRIdS"
C99 specifies
+ %zd
+ C99 specifies
%td
0
- and NULL
(and, for C++11, nullptr
).
+ For pointers (address values), there is a choice between 0
,
+ NULL
, and nullptr
.
For projects that allow C++11 features, use nullptr
.
For C++03 projects, we prefer NULL
because it looks like a
pointer. In fact, some C++ compilers provide special definitions of
@@ -2817,6 +3192,58 @@ Tashana Landray
A @const
annotation on a method additionally
- implies that the method should not be overridden in subclasses.
+ implies that the method cannot not be overridden in subclasses.
A @const
annotation on a constructor implies the
+ class cannot be subclassed (akin to final
in Java).
+
The open source compiler will allow the symbol it to be +
The open source compiler will allow the symbol to be
overwritten because the constant is
not marked as @const
.
In this case, the pointer can never be overwritten, but
value is highly mutable and not constant (and thus in
camelCase
, not ALL_CAPS
).
x[ffVersion][isIE]()
.die
is called unless
- resultOfOperation()
is NaN
and
- THINGS_TO_EAT
gets assigned the result of
- die()
.x[ffVersion, ieVersion][isIE]()
.
+ die
is always called since the array minus 1 is
+ NaN
which is never equal to anything (not even if
+ resultOfOperation()
returns NaN
) and
+ THINGS_TO_EAT
gets assigned the result of
+ die()
.