2009-10-09 14 views
5

En C++ que tienen una función que sólo requiere acceso de sólo lectura a una matriz, pero se declaró erróneamente como recibir un puntero no constante:¿Está permitido utilizar const_cast para el acceso de solo lectura a un objeto const?

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; 
} 

y necesito llamarlo para una matriz const:

static const int Array[] = { 10, 20, 0, 2}; 

countZeroes(const_cast<int*>(Array), sizeof(Array)/sizeof(Array[0])); 

será este comportamiento indefinido? Si es así, ¿cuándo se ejecutará el programa en UB? ¿Cuándo se realiza el const_cast y se llama a la función o cuando se accede a la matriz?

+0

Supongo que no puede cambiar la declaración de la función ... pero le recomiendo encarecidamente que escriba una envoltura con una mejor y haga el trabajo sucio dentro de ella. –

+0

quizás tratar una cosa totalmente diferente: 'size_t numZeros = std :: count (Array, Array + sizeof (Array)/sizeof (Array [0]), 0);' – MP24

+0

@ MP24 Esta función es sólo una simple ilustración de un problema. – sharptooth

Respuesta

13

Sí, se permite (si es peligroso!). Es la escritura real de un objeto const que incurre en un comportamiento indefinido, no el molde en sí (7.1.5.1/4 [dcl.type.cv]).

Como indica la norma en 5.2.11/7 [expr.const.cast], dependiendo del tipo del objeto, un intento de escribir a través de un puntero que es el resultado de descartar const puede producir un comportamiento indefinido.

-2

El uso de const_cast en un objeto que inicialmente se define como const es UB, por lo tanto, el comportamiento indefinido se produce inmediatamente en el punto al que llama const_cast.

+3

No. UB está en el momento de escribir en un objeto const, sin eliminar la constness. –

+0

Ah, claro, lo siento me dieron algunos consejos contradictorios sobre la interwebs –

+3

Esas redes pueden ser complicado. – GManNickG

1

Dado que su código no modifica la matriz, y le dijo al compilador que sabe lo que está haciendo utilizando el const_cast, en realidad estará bien. Sin embargo, creo que estás técnicamente invocando un comportamiento indefinido. Lo mejor es arreglar la declaración de la función, o escribir, declarar y usar la versión const-safe de la misma.

+0

intente leer sobre cómo usar const en "C++ efectivo" o "C++ más efectivo". Muestra algunos usos válidos del const_cast también (por ejemplo, para evitar la duplicación de código). –

+0

-1 porque esto no es un comportamiento indefinido; históricamente, habría dificultado la interoperación del código C++ 98 con el pre-estándar C. Sin embargo, estoy totalmente de acuerdo con el consejo. –

1

Sí, se puede hacer eso. No, no es un comportamiento indefinido siempre que la función realmente no intente escribir en la matriz.

1

El problema de const_cast es siempre el mismo - le permite "romper las reglas", al igual que desde y hacia void* - seguro que puede hacerlo, pero la pregunta es ¿por qué debería hacerlo?

En este caso, por supuesto está bien, pero debe preguntarse por qué no declaró size_t countZeroes(const int* array, size_t count) en primer lugar?

Y como regla general sobre const_cast:

  1. Se puede producir difícil de encontrar errores
  2. vaya a desechar la const-acuerdo con el compilador
  3. Básicamente que está girando el idioma en un nivel inferior.
Cuestiones relacionadas