template
nullptr
instead of NULL
or 0
*.h
if *-inl.h
has already been includedUnfortunately, 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:
char* buffer;
instead of char *buffer;
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.
VeryLongTypeName very_long_result = SomeValueWithAVeryLongName + SomeOtherValueWithAVeryLongName;
Operators are before the line break in these cases.
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, ...);
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) {
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. };
int FunctionThatDoesSomething(const char* important_string) { const char* pointer_into_string = important_string; }
class Foo { private: int counter_ = 0; };
template
template <typename T> class FancyContainer { ... }
(type)value
)dynamic_cast
does not work because RTTI is not enabledstatic_cast
for casting whenever it worksreinterpret_cast
is okay if static_cast
is not appropriateMalloc()
, Calloc()
, etc. from util.h
abort in Out-of-Memory situationsUncheckedMalloc()
, etc. return nullptr
in OOM situationsnullptr
instead of NULL
or 0
What it says in the title.
*.h
if *-inl.h
has already been includedDo
#include "util-inl.h" // already includes util.h
instead of
#include "util.h" #include "util-inl.h"
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.
“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
.