O uso const_cast para acesso somente leitura a um objeto const é permitido?
-
20-09-2019 - |
Pergunta
Em C ++, tenho uma função que requer apenas acesso somente leitura a uma matriz, mas é declarado por engano como recebendo um ponteiro que não é consagrado:
size_t countZeroes( int* array, size_t count )
{
size_t result = 0;
for( size_t i = 0; i < count; i++ ) {
if( array[i] == 0 ) {
++result;
}
}
return result;
}
E eu preciso chamá -lo para uma matriz const:
static const int Array[] = { 10, 20, 0, 2};
countZeroes( const_cast<int*>( Array ), sizeof( Array ) / sizeof( Array[0] ) );
Isso será um comportamento indefinido? Em caso afirmativo - quando o programa se deparará com o UB - ao fazer o const_cast e ligar para o functon ou ao acessar a matriz?
Solução
Sim, é permitido (se perigoso!). É a gravação real para um const
Objeto que incorre em comportamento indefinido, não o próprio elenco (7.1.5.1/4 [dcl.type.cv]).
Como as notas padrão em 5.2.11/7 [expr.const.cast], dependendo do tipo de objeto, uma tentativa de escrever através de um ponteiro que é o resultado de eliminar const
pode produzir comportamento indefinido.
Outras dicas
Como seu código não modifica a matriz, e você disse ao compilador, sabe o que está fazendo usando o const_cast
, você realmente ficará bem. No entanto, acredito que você está tecnicamente invocando um comportamento indefinido. É melhor consertar a declaração da função ou escrever e usar a versão segura para const.
Sim, você pode fazer isso. Não, não é um comportamento indefinido, desde que a função realmente não tente escrever na matriz.
O problema de const_cast
é sempre o mesmo - ele permite que você "quebre as regras", assim como o lançamento de e de void*
- Claro que você pode fazer isso, mas a pergunta é por que você deveria?
Nesse caso, é claro que está bem, mas você deve se perguntar por que não declarou size_t countZeroes( const int* array, size_t count )
em primeiro lugar?
E como uma regra geral sobre const_cast
:
- Pode produzir difíceis de encontrar bugs
- Você está jogando fora o alimento const-const com o compilador
- Basicamente, você está transformando o idioma em um de nível inferior.
Usando const_cast
em um objeto que é inicialmente definido como const
é UB, portanto o comportamento indefinido ocorre imediatamente no ponto em que você liga const_cast
.