Aviso C26415

O parâmetro de ponteiro inteligente é usado apenas para acessar o ponteiro contido. Em vez disso, use T* ou T& em vez disso.

Diretrizes Principais do C++: R.30: Use ponteiros inteligentes como parâmetros apenas para expressar explicitamente a semântica de tempo de vida

Usar um tipo de ponteiro inteligente para passar dados para uma função indica que a função de destino precisa gerenciar o tempo de vida do objeto contido. No entanto, digamos que a função usa apenas o ponteiro inteligente para acessar o objeto contido e nunca realmente chama qualquer código que possa levar à sua desalocação (ou seja, nunca afeta sua vida útil). Então, geralmente não há necessidade de complicar a interface com ponteiros inteligentes. É preferível um ponteiro simples ou uma referência ao objeto contido.

Comentários

Essa verificação abrange a maioria dos cenários que também causam C26410, C26415, C26417 e C26418. É melhor limpar SMART_PTR_NOT_NEEDED primeiro e, em seguida, alternar para casos de borda para ponteiros compartilhados ou exclusivos. Para uma limpeza mais focada, esse aviso pode ser desabilitado.

Além dos modelos padrão std::unqiue_pointer e std::shared_pointer, essa verificação reconhece tipos definidos pelo usuário que tenham probabilidade de ser ponteiros inteligentes. Esses tipos devem definir as seguintes operações:

  • Operadores de acesso de membro ou de desreferência sobrecarregados que são públicos e não marcados como excluídos.
  • Destruidor público que não é excluído ou padrão, incluindo destruidores que são explicitamente definidos vazios.

A interpretação das operações que podem afetar o tempo de vida dos objetos contidos é ampla e inclui:

  • Qualquer função que aceite um ponteiro ou parâmetro de referência para um ponteiro inteligente não constante
  • Copiar ou mover construtores ou operadores de atribuição
  • Funções não constantes

Exemplos

Gerenciamento de tempo de vida complicado.

bool set_initial_message(
            const std::unique_ptr<message> &m) // C26415, also C26410 NO_REF_TO_CONST_UNIQUE_PTR
{
    if (!m || initial_message_)
        return false;

    initial_message_.reset(m.get());
    return true;
}

void pass_message(const message_info &info)
{
    auto m = std::make_unique<message>(info);
    const auto release = set_initial_message(m);
    // ...
    if (release)
        m.release();
}

Gerenciamento de tempo de vida complicado – retrabalhado.

void set_initial_message(std::shared_ptr<message> m) noexcept
{
    if (m && !initial_message_)
        initial_message_ = std::move(m);
}

void pass_message(const message_info &info)
{
    auto m = std::make_shared<message>(info);
    set_initial_message(m);
    // ...
}