C26444 NO_UNNAMED_RAII_OBJECTS

Avoid unnamed objects with custom construction and destruction.

C++ Core Guidelines

ES.84: Don't (try to) declare a local variable with no name

Unnamed (that is, temporary) objects with non-trivial behavior may point to either (a) inefficient code that allocates and immediately throws away resources or (b) to the code that unintentionally ignores non-primitive data. Sometimes it may also indicate plainly wrong declaration.

Notes

  • This rule detects types with non-deleted destructors. Keep in mind that destructors can be compiler generated.
  • The warning can flag code that is not compiler generated and that invokes either a non-default constructor of a RAII type or a function that returns an object of such type. This warning helps to detect ignored call results in addition to wrong declarations.
  • The logic skips temporaries if they are used in higher-level expressions. One example is temporaries that are passed as arguments or used to invoke a function.
  • The standard library implementation may have different versions of destruction logic for some types (for example, containers). This can produce noisy warnings on debug builds because it is customary to ignore iterators returned from calls like std::vector::insert. While such warnings are not actionable in the majority of cases, they are legitimate in pointing to the place where some non-obvious work is done in temporary objects.

Example: Ignored call result

std::string ToTraceMessage(State &state);
void SaveState(State &state)
{
    // ...
    ToTraceMessage(state); // C26444, should we do something with the result of this call?
}

Example: Ignored call result - fixed.
std::cerr << ToTraceMessage(state);

Example: Unexpected lifetime.
void SplitCache()
{
    gsl::finally([] { RestoreCache(); }); // C26444, RestoreCache is invoked immediately!
    //...
}

Example: Unexpected lifetime - fixed.
const auto _ = gsl::finally([] { RestoreCache(); });

See Also

ES.84: Don't (try to) declare a local variable with no name