Adds instructions on how to format C++ comments to the C++ style guide, as `cpplint.py` doesn't complain about C-style comments on the code. PR-URL: https://github.com/nodejs/node/pull/17617 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Anatoli Papirovski <apapirovski@mac.com> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
6.3 KiB
C++ Style Guide
Table of Contents
- Formatting
- Left-leaning (C++ style) asterisks for pointer declarations
- C++ style comments
- 2 spaces of indentation for blocks or bodies of conditionals
- 4 spaces of indentation for statement continuations
- Align function arguments vertically
- Initialization lists
- CamelCase for methods, functions, and classes
- snake_case for local variables and parameters
- snake_case_ for private class fields
- Space after
template
- Memory Management
- Others
Unfortunately, the C++ linter (based on
Google’s cpplint
), which can be run
explicitly via make lint-cpp
, does not currently catch a lot of rules that are
specific to the Node.js C++ code base. This document explains the most common of
these rules:
Formatting
Left-leaning (C++ style) asterisks for pointer declarations
char* buffer;
instead of char *buffer;
C++ style comments
Use C++ style comments (//
) for both single-line and multi-line comments.
Comments should also start with uppercase and finish with a dot.
Examples:
// A single-line comment.
// Multi-line comments
// should also use C++
// style comments.
The codebase may contain old C style comments (/* */
) from before this was the
preferred style. Feel free to update old comments to the preferred style when
working on code in the immediate vicinity or when changing/improving those
comments.
2 spaces of indentation for blocks or bodies of conditionals
if (foo)
bar();
or
if (foo) {
bar();
baz();
}
Braces are optional if the statement body only has one line.
namespace
s receive no indentation on their own.
4 spaces of indentation for statement continuations
VeryLongTypeName very_long_result = SomeValueWithAVeryLongName +
SomeOtherValueWithAVeryLongName;
Operators are before the line break in these cases.
Align function arguments vertically
void FunctionWithAVeryLongName(int parameter_with_a_very_long_name,
double other_parameter_with_a_very_long_name,
...);
If that doesn’t work, break after the (
and use 4 spaces of indentation:
void FunctionWithAReallyReallyReallyLongNameSeriouslyStopIt(
int okay_there_is_no_space_left_in_the_previous_line,
...);
Initialization lists
Long initialization lists are formatted like this:
HandleWrap::HandleWrap(Environment* env,
Local<Object> object,
uv_handle_t* handle,
AsyncWrap::ProviderType provider)
: AsyncWrap(env, object, provider),
state_(kInitialized),
handle_(handle) {
CamelCase for methods, functions, and classes
Exceptions are simple getters/setters, which are named property_name()
and
set_property_name()
, respectively.
class FooBar {
public:
void DoSomething();
static void DoSomethingButItsStaticInstead();
void set_foo_flag(int flag_value);
int foo_flag() const; // Use const-correctness whenever possible.
};
snake_case for local variables and parameters
int FunctionThatDoesSomething(const char* important_string) {
const char* pointer_into_string = important_string;
}
snake_case_ for private class fields
class Foo {
private:
int counter_ = 0;
};
Space after template
template <typename T>
class FancyContainer {
...
}
Memory Management
Memory allocation
Malloc()
,Calloc()
, etc. fromutil.h
abort in Out-of-Memory situationsUncheckedMalloc()
, etc. returnnullptr
in OOM situations
Use nullptr
instead of NULL
or 0
What it says in the title.
Ownership and Smart Pointers
"Smart" pointers are classes that act like pointers, e.g.
by overloading the *
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.
std::shared_ptr
is a smart pointer type that expresses shared ownership of a
dynamically allocated object. std::shared_ptr
s can be copied; ownership
of the object is shared among all copies, and the object
is deleted when the last std::shared_ptr
is destroyed.
Prefer to use std::unique_ptr
to make ownership
transfer explicit. For example:
std::unique_ptr<Foo> FooFactory();
void FooConsumer(std::unique_ptr<Foo> ptr);
Never use std::auto_ptr
. Instead, use std::unique_ptr
.
Others
Type casting
- Always avoid C-style casts (
(type)value
) dynamic_cast
does not work because RTTI is not enabled- Use
static_cast
for casting whenever it works reinterpret_cast
is okay ifstatic_cast
is not appropriate
Do not include *.h
if *-inl.h
has already been included
Do
#include "util-inl.h" // already includes util.h
instead of
#include "util.h"
#include "util-inl.h"
Avoid throwing JavaScript errors in nested C++ methods
If you need to throw JavaScript errors from a C++ binding method, try to do it at the top level and not inside of nested calls.
A lot of code inside Node.js is written so that typechecking etc. is performed in JavaScript.
Using C++ throw
is not allowed.