C26414 RESET_LOCAL_SMART_PTR

"Move, copy, reassign or reset a local smart pointer."

C++ Core Guidelines: R.5: Prefer scoped objects, don't heap-allocate unnecessarily

Smart pointers are convenient for dynamic resource management, but they are not always necessary. For example, creating of a local dynamic buffer can be easily (end sometimes more efficiently) managed by standard containers. For single objects it may be unnecessary to do dynamic allocation at all (e.g. if such objects never outlive their creator function) and they can be replaced with local variables. Smart pointers become handy when scenario requires changing of ownership, i.e. reassigning of a dynamic resource multiple times or in multiple paths. This also includes cases where resources are obtained from external code and smart pointers are used to extend resource’s lifetime.

Remarks

  • In addition to the standard std::unique_pointer and std::shared_pointer templates, this check recognizes user defined types which are likely intended to be smart pointers. Such types are expected to define the following operations:
    • overloaded dereference or member access operators, that are public and not marked as deleted;
    • public destructor which is neither deleted nor defaulted. This includes destructors which are explicitly defined empty.
    • The type Microsoft::WRL::ComPtr behaves as a shared pointer, but it is often used in quite specific scenarios which are affected by the COM lifetime management. To avoid excessive noise this type is filtered out.
    • This check looks for explicit local allocations assigned to smart pointers to identify if scoped variables could word as an alternative. In addition to direct calls to operator new, special functions like std::make_unique and std::make_shared are also interpreted as direct allocations.

Example

dynamic buffer

void unpack_and_send(const frame &f)
{
    auto buffer = std::make_unique<char[]>(f.size()); // C26414
    f.unpack(buffer.get());
    // ...
}

dynamic buffer – replaced by container

void unpack_and_send(const frame &f)
{
    auto buffer = std::vector<char>(f.size());
    f.unpack(buffer.data());
    // ...
}