Tenho o seguinte código:
void check_portvalue(std::string_view value)
{
[[maybe_unused]] port_t test {value};
}
O objeto test
permanece sem uso, mas a criação serve como uma verificação, porque o construtor pode lançar. O [[maybe_unused]]
atributo suprime o aviso do compilador.
Mas já que o compilador detecta que isso não é utilizado, ele poderia otimizar a instrução inteira e assim evitar que a exceção fosse lançada?
O otimizador deve seguir a regra como se (ou seja, não pode alterar "comportamentos observáveis")
A única exceção à regra "como se" são:
Seu código não se enquadra nessas categorias.
Nenhuma otimização pode remover a chamada do construtor no seu exemplo. Seu exemplo não deve realmente disparar o aviso mesmo sem
[[maybe_unused]
. Além disso, quando a função não faz nada além de criar o objeto, você também pode usar um temporário sem nomeport_t{value};
para o mesmo efeito.O restante da resposta tenta explicar isso em detalhes.
Considere este exemplo:
Completar isso com avisos habilitados (gcc:
-Werror -Wall
) não produz avisos e a saída é ( https://godbolt.org/z/TnoPMWbcs ):Na verdade, esse padrão RAII (alocação de recursos é aquisição) é tão comum em C++ que os compiladores podem facilmente identificá-lo e não emitirão um aviso para a variável não utilizada. O "uso" da variável é manter o objeto vivo até o fim do escopo para que
bye
apareça por último. Nenhuma otimização é permitida para alterar a ordem da saída ou fazer com que a saída não apareça. Geralmente, as otimizações não alteram o comportamento observável de um programa (com poucas exceções não relevantes aqui).Deixando isso de lado, vamos considerar um exemplo diferente que realmente dispara o aviso (de novo
-Wall -Werror
):Saída do gcc ( https://godbolt.org/z/f47Pcsao5 ):
É apenas um aviso, para que possamos
[[maybe_unused]]
( https://godbolt.org/z/qM3dK4jbn )Em qualquer caso, a saída da chamada da função deve aparecer.
Em relação ao aviso, note que geralmente avisos não são obrigatórios pelo padrão. Even
[[maybe_unused]]
é meramente uma recomendação aos compiladores. Um compilador pode ignorar o atributo e ainda estar em conformidade com o padrão.Imagine que o autor considerou
fee
um nome ruim para o que a função faz no contexto deber
. Ele escolheu dar um nome muito melhorf
. Imagine ainda que ele não queira ignorar o aviso. Antes do C++17, era preciso recorrer a hacks para silenciar o aviso. Com o C++17,[[maybe_unused]]
não é mais preciso recorrer a hacks. Um futuro leitor não precisa depender de avisos. Uma variável declarada como[[maybe_unsued]]
não precisa navegar em potencialmente muitas linhas de código para ver que não é usada, mas recebeu um nome propositalmente.