Chromium C++ style guide
Chromium follows the Google C++ Style Guide unless an exception is listed below.
Code formatting
Put * and & by the type rather than the variable name.
In class declarations, group function overrides together within each access control section, with one
labeled group per parent class.
Prefer (foo == 0) to (0 == foo).
Use {} on all conditionals/loops
Naming
1. There are generally two acceptable and internally consistent naming conventions.
a) The "camel case" convention:
class AwesomeWidget; // classes: upper-case & camel case
double distanceFromPoint = 5.0; // variables: lower-case & camel case
double computeDistance(); // functions: lower-case & camel case
double AwesomeWidget::getFoo(); // member functions: lower-case & camel
case
enum class State { CorruptData }; // enums: upper-case & camel case
Only class names start with an upper-case letter, whereas variable and function names start with a
lower-case letter. All following syllables are directly connected to the preceding syllable and begin with
an upper-case letter.
b) The "underscores" or "snake case" convention:
class Awesome_widget; // classes: begin upper-case &
underscore separators
class AwesomeWidget; // some use camel case here (Python-
like)
double distance_from_point = 5.0; // variables: lower-case & underscore
separators
double compute_distance(); // functions: lower-case & underscore
separators
double Awesome_widget::get_foo(); // member functions: lower-case &
underscore separators
enum class State { corrupt_data }; // enums: like classes; elements
lower-case & underscore separators
Only class names start with an upper-case letter, whereas variable and function names start with a
lower-case letter. All following syllables are separated by an underscore (_) and keep the case of the
preceding syllable(s).
Use one of these naming conventions consistently throughout all related projects. Do not mix
styles or deviate from the chosen convention.
2. Class names and enumerations shall always begin with an upper-case letter, in order to cleanly
distinguish them from (instance) variables. Never declare classes that begin with a lower-case letter.
Example:
class Widget;
Widget widget;
enum class Level : unsigned char;
Class and enumeration types are not variable names, and a visual separation is clearly desirable.
Using uppercase identifiers for the former and lowercase identifiers for the latter is an
unambiguous way to distinguish the two, and everyone immediately knows which one is which.
Constructions like
widget my_widget; // funny name
widget w; // name not expressive at all
will just lead to decreased readability at some point, and
widget widget; // the obvious naming in many cases
is not legal code (unless the first letter of the class type becomes uppercase).
There shall be no class or struct name in the codebase that begins with a lower-case letter.
2. Variable names shall therefore always begin with a lower-case letter.
Example:
int index;
Widget widget;
There shall be no variable in the codebase that begins with an upper-case letter.
3. Both member and non-member functions shall always begin with a lower-case letter.
Example:
double compute_distance();
const std::string& Window::name();
Not:
double ComputeDistance();
Function names are not class names, so prevent any possible confusion.
There shall be no function or member function in the codebase that begins with an upper-case
letter.
C++ Style Guide
‘auto’ shouldn't be used that much anyway
some sort of prefix for class member variables (we use 'm_' which is common in a lot of Microsoft code)
ALL CAPS should be reserved for macros and macros only
use const consistently (check if member functions modify their object; check if functions modify
arguments passed by pointer or reference)
flag uses of casts (casts neuter the type system)
1. Opening braces (for classes, functions, control blocks, etc.) should reside on a new empty line.
for (int i = 0; i < 4; ++i)
{
// ...
}
2. Egyptian-style braces (where the opening brace is kept on the line end) are discouraged.
for (int i = 0; i < 4; ++i) { // discouraged
// ...
}
3. Avoid placing pointer and reference type symbols adjacent to a variable or function name.
Example:
int* p;
int& q = *p;
lint-like guidelines for C++?
A class Fred’s assignment operator should return *this as a Fred& (allows chaining of assignments)
A class with any virtual functions ought to have a virtual destructor
A class with any of {destructor, copy assignment operator, copy constructor, move
assignment operator, move constructor} generally needs all 5
A class Fred’s copy constructor and assignment operator should have const in the parameter:
respectively Fred::Fred(const Fred&) and Fred& Fred::operator= (const Fred&)
When initializing an object’s member objects in the constructor, always use initialization lists rather
than assignment. The performance difference for user-defined classes can be substantial (3x!)
Assignment operators should make sure that self assignment does nothing, otherwise you may have
a disaster. In some cases, this may require you to add an explicit test to your assignment operators.
When you overload operators, abide by the guidelines. For example, in classes that define
both += and +, a += b and a = a + b should generally do the same thing; ditto for the other identities
of built-in/intrinsic types (e.g., a += 1 and ++a; p[i] and *(p+i); etc). This can be enforced by writing
the binary operations using the op= forms. E.g.,
1. Fred operator+ (const Fred& a, const Fred& b)
2. {
3. Fred ans = a;
4. ans += b;
5. return ans;
6. }
This way the “constructive” binary operators don’t even need to be friends. But it is sometimes possible
to more efficiently implement common operations (e.g., if class Fred is actually std::string, and += has to
reallocate/copy string memory, it may be better to know the eventual length from the beginning).
Express intent
Example
gsl::index i = 0;
while (i < v.size()) {
// ... do something with v[i] ...
}
Better:
for (const auto& x : v) { /* do something with the value of x */ }
OR
for_each(v, [](int x) { /* do something with the value of x */ });
for_each(par, v, [](int x) { /* do something with the value of x */ });
Common C++ Naming Conventions
Types start with upper case: MyClass.
Functions and variables start with lower case: myMethod (
Names representing methods or functions must be verbs and written in mixed case starting with lower
case e.g.
getName(), computeTotalWidth() )
Constants are all upper case: const double PI=3.14159265358979323;
C++ Standard Library use these guidelines:
Macro names use upper case with underscores: INT_MAX.
Template parameter names use camel case: InputIterator.
All other names use snake case: unordered_map.
Global variables should always be referred to using the :: operator.
::mainWindow.open(), ::applicationContext.getName()
In general, the use of global variables should be avoided. Consider using singleton objects
instead.
Distinguish Private Object Data
Name private data with a m_ prefix to distinguish it from public data. m_ stands for "member" data.
Distinguish Function Parameters
Name function parameters with an t_ prefix. t_ can be thought of as "the", but the meaning is
arbitrary. The point is to distinguish function parameters from other variables in scope while giving
us a consistent naming strategy.
class PrivateSize
{
public:
int width() const { return m_width; }
int height() const { return m_height; }
PrivateSize(int t_width, int t_height) : m_width(t_width), m_height(t_height) {}
private:
int m_width;
int m_height;
};
Include Guards
Header files must contain a distinctly-named include guard to avoid problems with including the same
header multiple times and to prevent conflicts with headers from other projects.
#ifndef MYPROJECT_MYCLASS_HPP
#define MYPROJECT_MYCLASS_HPP
namespace MyProject {
class MyClass {
};
}
#endif
Use "" for Including Local Files
... <> is reserved for system includes.
// Bad Idea. Requires extra -I directives to the compiler
// and goes against standards.
#include <string>
#include <includes/MyHeader.hpp>
// Good Idea
// Requires no extra params and notifies the user that the file
// is a local file.
#include <string>
#include "MyHeader.hpp"
Initialize Member Variables
...with the member initializer list.
For POD types, the performance of an initializer list is the same as manual initialization, but for other
types there is a clear performance gain, see below.
// Bad Idea
class MyClass
{
public:
MyClass(int t_value)
{
m_value = t_value;
}
private:
int m_value;
};
// Bad Idea
// This leads to an additional constructor call for m_myOtherClass
// before the assignment.
class MyClass
{
public:
MyClass(MyOtherClass t_myOtherClass)
{
m_myOtherClass = t_myOtherClass;
}
private:
MyOtherClass m_myOtherClass;
};
// Good Idea
// There is no performance gain here but the code is cleaner.
class MyClass
{
public:
MyClass(int t_value)
: m_value(t_value)
{
}
private:
int m_value;
};
// Good Idea
// The default constructor for m_myOtherClass is never called here, so
// there is a performance gain if MyOtherClass is not
is_trivially_default_constructible.
class MyClass
{
public:
MyClass(MyOtherClass t_myOtherClass)
: m_myOtherClass(t_myOtherClass)
{
}
private:
MyOtherClass m_myOtherClass;
};
In C++11 you can assign default values to each member (using = or using {}).
Assigning default values with =
// ... //
private:
int m_value = 0; // allowed
unsigned m_value_2 = -1; // narrowing from signed to unsigned allowed
// ... //
This ensures that no constructor ever "forgets" to initialize a member object.
Assigning default values with brace initialization
Using brace initialization does not allow narrowing at compile-time.
// Best Idea
// ... //
private:
int m_value{ 0 }; // allowed
unsigned m_value_2 { -1 }; // narrowing from signed to unsigned not allowed, leads
to a compile time error
// ... //
Prefer {} initialization over = unless you have a strong reason not to.
Forgetting to initialize a member is a source of undefined behavior bugs which are often
extremely hard to find.
If the member variable is not expected to change after the initialization, then mark it const.
class MyClass
{
public:
MyClass(int t_value)
: m_value{t_value}
{
}
private:
const int m_value{0};
};
Since a const member variable cannot be assigned a new value, such a class may not have
a meaningful copy assignment operator.
Avoid Raw Memory Access
Raw memory access, allocation and deallocation, are difficult to get correct in C++
without risking memory errors and leaks . C++11 provides tools to avoid these problems.
// Bad Idea
MyClass *myobj = new MyClass;
// ...
delete myobj;
// Good Idea
auto myobj = std::make_unique<MyClass>(constructor_param1, constructor_param2); //
C++14
auto myobj = std::unique_ptr<MyClass>(new MyClass(constructor_param1,
constructor_param2)); // C++11
auto mybuffer = std::make_unique<char[]>(length); // C++14
auto mybuffer = std::unique_ptr<char[]>(new char[length]); // C++11
// or for reference counted objects
auto myobj = std::make_shared<MyClass>();
// ...
// myobj is automatically freed for you whenever it is no longer used.
Use Initializer Lists
// This
std::vector<ModelObject> mos{mo1, mo2};
// -or-
auto mos = std::vector<ModelObject>{mo1, mo2};
// Don't do this
std::vector<ModelObject> mos;
mos.push_back(mo1);
mos.push_back(mo2);
Initializer lists are significantly more efficient; reducing object copies and resizing of
containers.
Prefer unique_ptr to shared_ptr
If possible use unique_ptr instead of shared_ptr. The unique_ptr does not need to keep track of its
copies because it is not copyable. Because of this it is more efficient than the shared_ptr. Equivalent
to shared_ptr and make_shared you should use make_unique (C++14 or greater) to create
the unique_ptr:
std::make_unique<ModelObject_Impl>();
Current best practices suggest returning a unique_ptr from factory functions as well, then converting
the unique_ptr to a shared_ptr if necessary.
std::unique_ptr<ModelObject_Impl> factory();
auto shared = std::shared_ptr<ModelObject_Impl>(factory());
Google C++ Style Guide
https://medium.com/@mandolkarmakarand94/key-points-google-c-style-guide-
ace14236ecdf
1. Naming Conventions
Variable Names: Use snake_case for variable names (e.g., my_variable).
Function Names: Use CamelCase for function names (e.g., DoSomething).
Class Names: Use CamelCase for class names (e.g., MyClass).
Constant Names: Use kCamelCase for constant names (e.g., kMaxValue).
Namespace Names: Use snake_case for namespaces (e.g., namespace
my_namespace).
2. Header Files
File Extensions: Use .h for header files and .cc for implementation files.
Include Guards: Every header file should have #ifndef, #define, and #endif include guards to
prevent multiple inclusions (or use #pragma once).
Include Order: Include headers in the following order: related headers, C++ standard library
headers, other library headers, project headers.
Transition from C to C++
1.#define statements should be avoided
const double PI = 3.1415; // NOT: #define PI 3.1415
2.The iostream library should be preferred to stdio
#include <iostream> // NOT: #include <stdio.h>
3. C++ style casts should be preferred to C style casts.
static_cast<double> intValue; // NOT: (double) intValue
4. References should be preferred to pointers.
Pointers should be used if and only if it should be possible for the referred
object to be null.
Example: If a person is modelled as an object, the persons parents should be
references to persons (everybody has parents) while siblings should be
pointers to persons.
5. const should be used wherever possible.
7. Pass-by-value should be avoided for objects.
myMethod (const SomeClass &object) // NOT: myMethod (SomeClass object)
There are two reasons for this. First is of performance. Pass by value for
objects always involves creating a temporar object using the copy constructor
of the objects class and destroying the object again on the method exit.
Second reason is that objects passed by value through a base-class variable
will in effect behave as a base-class object without the extended information
defined by the derived class.
8. Variable argument lists (...) should be avoided.
Variable argument lists prohibit strong type checking as provided by C++
9. new and delete should be preferred to malloc, realloc and free.
18. "Isa" relationship should be modelled by inheritance, "has-a" should be modelled
by containment.
class B : public A // B "is-a" A
{
...
}
class B
{
...
private:
A a_; // B "has-a" A
}
19. Non-virtual methods must never be redefined by a subclass.
26. Singleton objects should be preferred to global variables.
17. The terms get/set must be used where an attribute is accessed directly.
employee.getName(); employee.setName(name); matrix.getElement(2, 4);
matrix.setElement(2, 4, value);
18. The term compute can be used in methods where something is computed.
valueSet->computeAverage(); matrix->computeInverse()
19. The term find can be used in methods where something is looked up.
vertex.findNearestVertex(); matrix.findMinElement();
20. The term initialize can be used where an object or a concept is established.
printer.initializeFontSet();
22. Plural form should be used on names representing a collection of objects.
vector<Point> points; int values[];
23. The prefix n should be used for variables representing a number of objects.
nPoints, nLines
26. The prefix is should be used for boolean variables and methods.
isSet, isVisible, isFinished, isFound, isOpen
28. Abbreviations in names should be avoided.
computeAverage(); // NOT: compAvg();
31. Enumeration constants can be prefixed by a common type name.
enum Color { COLOR_RED, COLOR_GREEN, COLOR_BLUE };
48. Use of global variables should be minimized.
In C++ there is no reason global variables need to be used at all. The same is true for global
functions or file scope (static) variables.
51. C++ pointers and references should have their reference symbol next to the type rather
than to the name.
float* x; // NOT: float *x; int& y; // NOT: int &y;
49. Class variables should never be declared public.
54. Variables should be declared in the smallest scope possible.
Keeping the operations on a variable within a small scope, it is easier to control the effects and
side effects of the variable.