Pregunta

Entiendo que la función no puede cambiar el estado del objeto, pero pensé haber leído en alguna parte que al compilador se le permitió asumir que si la función se llamaba con los mismos argumentos, devolvería el mismo valor y, por lo tanto, podría reutilizarse. un valor almacenado en caché si estaba disponible.p.ej.

class object
{
    int get_value(int n) const
    {
        ...
    }

...


object x;

int a = x.get_value(1);
    ...
int b = x.get_value(1);

entonces el compilador podría optimizar la segunda llamada y usar el valor en un registro o simplemente hacer b = a;

¿Es esto cierto?

¿Fue útil?

Solución

const Se trata de la semántica del programa y no de detalles de implementación.Deberías marcar una función miembro. const cuando no cambia el estado visible del objeto y debería poder invocarse en un objeto que es en sí mismo const.Dentro de un const función miembro en una clase X, el tipo de this es X const *:puntero a constante X objeto.Por lo tanto, todas las variables miembro son efectivamente const dentro de esa función miembro (excepto mutable unos).Si tienes un const objeto, sólo puedes llamar const funciones miembro en él.

Puedes usar mutable para indicar que una variable miembro puede cambiar incluso dentro de un const función miembro.Esto generalmente se usa para identificar variables utilizadas para almacenar en caché los resultados, o para variables que no afectan el estado observable real, como los mutex (aún es necesario bloquear el mutex en el const funciones miembro) o utilizar contadores.

class X
{
    int data;
    mutable boost::mutex m;
public:
    void set_data(int i)
    {
        boost::lock_guard<boost::mutex> lk(m);
        data=i;
    }
    int get_data() const // we want to be able to get the data on a const object
    {
        boost::lock_guard<boost::mutex> lk(m); // this requires m to be non-const
        return data;
    }
};

Si mantiene los datos por puntero en lugar de hacerlo directamente (incluidos punteros inteligentes como std::auto_ptr o boost::shared_ptr) entonces el puntero se convierte const en un const función miembro, pero no los datos apuntados, por lo que puede modificar los datos apuntados.

En cuanto al almacenamiento en caché:en general, el compilador no puede hacer esto porque el estado puede cambiar entre llamadas (especialmente en mi ejemplo de subprocesos múltiples con el mutex).Sin embargo, si la definición está en línea, el compilador puede introducir el código en la función de llamada y optimizar lo que puede ver allí.Esto podría resultar en la función efectivamente solo ser llamado una vez.

La próxima versión del Estándar C++ (C++0x) tendrá una nueva palabra clave constexpr.Funciones etiquetadas constexpr Devuelve un valor constante, por lo que los resultados se pueden almacenar en caché.Existen límites sobre lo que puede hacer en dicha función (para que el compilador pueda verificar este hecho).

Otros consejos

La palabra clave mudable en variables miembro permite que funciones constantes alteren el estado del objeto en cuestión.

Y no, no almacena datos en caché (al menos no todas las llamadas), ya que el siguiente código es una función constante válida que cambia con el tiempo:

int something() const { return m_pSomeObject->NextValue(); }

Tenga en cuenta que el puntero puede ser constante, aunque el objeto al que apunta no es constante, por lo tanto, la llamada a NextValue en SomeObject puede alterar o no su propio estado interno.Esto hace que la función algo devuelva valores diferentes cada vez que se llama.

Sin embargo, no puedo responder cómo funciona el compilador con métodos constantes.He oído que puede optimizar ciertas cosas, aunque tendría que buscarlo para estar seguro.

No.

Un método constante es un método que no cambia el estado del objeto (es decir,sus campos), pero no se puede asumir que dada la misma entrada, se determina el valor de retorno de un método constante.En otras palabras, const La palabra clave NO implica que la función sea uno a uno.Por ejemplo, un método que devuelve la hora actual es un método constante pero su valor de retorno cambia entre llamadas.

La palabra clave const en una función miembro marca el este parámetro como constante.La función aún puede silenciar datos globales (por lo que no se pueden almacenar en caché), pero no datos de objetos (lo que permite llamadas a objetos constantes).

En este contexto, un const función miembro significa que this es tratado como un const puntero también.En términos prácticos, significa que no se le permite modificar el estado de this dentro de una const función miembro.

Para funciones sin efectos secundarios (es decir, lo que estás tratando de lograr), GCC tiene un "atributo de función" llamado pure (lo usas diciendo __attribute__((pure))): http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

Lo dudo, la función aún podría llamar a una función global que alterara el estado del mundo y no violara la constante.

Además del hecho de que la función miembro puede modificar datos globales, es posible que la función miembro modifique miembros mutables declarados explícitamente del objeto en cuestión.

Corey tiene razón, pero tenga en cuenta que cualquier variable miembro que esté marcada como mudable poder modificarse en funciones miembro constantes.

También significa que estas funciones se pueden llamar desde otras funciones constantes o mediante otras referencias constantes.


Editar:Maldita sea, fui derrotado por 9 segundos....9!!!:)

Los métodos const también pueden modificar locales estáticos.Por ejemplo, lo siguiente es perfectamente legal (y las llamadas repetidas a bar() devolverán valores crecientes, no un 0 almacenado en caché):

class Foo
{
public:
    int bar() const
    {
        static int x = 0;
        return x++;
    }
};
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top