NoDestructor<T> is a wrapper around an object of type T that behaves as an object of type T but never calls T's destructor. NoDestructor<T> makes it safer and/or more efficient to use such objects in static storage contexts, ideally as function scope static variables.
Declared in <absl/base/no_destructor.h>
template<typename T>
class NoDestructor;
An instance of absl::NoDestructor<T> has similar type semantics to an instance of T:
* Constructs in the same manner as an object of type T through perfect forwarding. * Provides pointer/reference semantic access to the object of type T via ->, *, and get(). (Note that const NoDestructor<T> works like a pointer to const T.)
Additionally, NoDestructor<T> provides the following benefits:
* Never calls T's destructor for the object * If the object is a function-local static variable, the type can be lazily constructed.
An object of type NoDestructor<T> is "trivially destructible" in the notion that its destructor is never run.
Usage as Function Scope Static Variables
Function static objects will be lazily initialized within static storage:
// Function scope. const std::string& MyString() { static const absl::NoDestructor<std::string> x("foo"); return *x; }
For function static variables, NoDestructor avoids heap allocation and can be inlined in static storage, resulting in exactly-once, thread-safe construction of an object, and very fast access thereafter (the cost is a few extra cycles).
Using NoDestructor<T> in this manner is generally better than other patterns which require pointer chasing:
// Prefer using absl::NoDestructor<T> instead for the static variable. const std::string& MyString() { static const std::string* x = new std::string("foo"); return *x; }
Usage as Global Static Variables
NoDestructor<T> allows declaration of a global object of type T that has a non-trivial destructor since its destructor is never run. However, such objects still need to worry about initialization order, so such use is not recommended, strongly discouraged by the Google C++ Style Guide, and outright banned in Chromium. See https://google.github.io/styleguide/cppguide.html#Static_and_Global_Variables
// Global or namespace scope. absl::NoDestructor<MyRegistry> reg{"foo", "bar", 8008};
Note that if your object already has a trivial destructor, you don't need to use NoDestructor<T>.
| Name | Description |
|---|---|
NoDestructor [constructor] | Constructors |
operator= [deleted] | Deleted: NoDestructor is not copy-assignable. |
get | get overloads |
operator* | Dereference operators |
operator-> | Member access operators |
| Name | Description |
|---|---|
NoDestructor<T> | Provide 'Class Template Argument Deduction': the type of NoDestructor's T will be the same type as the argument passed to NoDestructor's constructor. |