Domanda

Capisco che alla funzione non è consentito modificare lo stato dell'oggetto, ma pensavo di aver letto da qualche parte che al compilatore era consentito presumere che se la funzione fosse stata chiamata con gli stessi argomenti, avrebbe restituito lo stesso valore e quindi avrebbe potuto riutilizzare un valore memorizzato nella cache, se disponibile.per esempio.

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

...


object x;

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

quindi il compilatore potrebbe ottimizzare la seconda chiamata e utilizzare il valore in un registro o semplicemente farlo b = a;

È vero?

È stato utile?

Soluzione

const riguarda la semantica del programma e non i dettagli di implementazione.Dovresti contrassegnare una funzione membro const quando non cambia lo stato visibile dell'oggetto e dovrebbe essere richiamabile su un oggetto che è esso stesso const.All'interno di una const funzione membro di una classe X, il tipo di this È X const *:puntatore alla costante X oggetto.Pertanto tutte le variabili membro sono effettivamente const all'interno di quella funzione membro (eccetto mutable quelli).Se hai un const oggetto, puoi solo chiamare const funzioni membro su di esso.

Puoi usare mutable per indicare che una variabile membro può cambiare anche all'interno di a const funzione membro.Questo viene in genere utilizzato per identificare le variabili utilizzate per la memorizzazione nella cache dei risultati o per variabili che non influenzano lo stato effettivamente osservabile come i mutex (è comunque necessario bloccare il mutex nel const funzioni membro) o utilizzare i contatori.

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

Se conservi i dati tramite puntatore anziché direttamente (inclusi puntatori intelligenti come std::auto_ptr O boost::shared_ptr) quindi il puntatore diventa const in un const funzione membro, ma non i dati puntati, quindi è possibile modificare i dati puntati.

Per quanto riguarda la memorizzazione nella cache:in generale il compilatore non può farlo perché lo stato potrebbe cambiare tra una chiamata e l'altra (specialmente nel mio esempio multi-thread con il mutex).Tuttavia, se la definizione è in linea, il compilatore può inserire il codice nella funzione chiamante e ottimizzare ciò che può vedere lì.Ciò potrebbe comportare la funzione effettivamente essere chiamato solo una volta.

La prossima versione del Standard C++ (C++0x) avrà una nuova parola chiave constexpr.Funzioni contrassegnate constexpr restituire un valore costante, in modo che i risultati possano essere memorizzati nella cache.Ci sono dei limiti su cosa puoi fare in tale funzione (in modo che il compilatore possa verificare questo fatto).

Altri suggerimenti

La parola chiave mutevole sulle variabili membro consente alle funzioni const di alterare lo stato dell'oggetto in questione.

E no, non memorizza nella cache i dati (almeno non tutte le chiamate) poiché il seguente codice è una funzione const valida che cambia nel tempo:

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

Si noti che il puntatore può essere const, sebbene l'oggetto puntato non sia const, pertanto la chiamata a NextValue su SomeObject può alterare o meno il proprio stato interno.Ciò fa sì che la funzione qualcosa restituisca valori diversi ogni volta che viene chiamata.

Tuttavia, non posso rispondere a come funziona il compilatore con i metodi const.Ho sentito dire che può ottimizzare alcune cose, anche se dovrei cercarlo per esserne sicuro.

NO.

Un metodo const è un metodo che non modifica lo stato dell'oggetto (es.i suoi campi), ma non si può presumere che, dato lo stesso input, venga determinato il valore restituito di un metodo const.In altre parole, const La parola chiave NON implica che la funzione sia uno a uno.Ad esempio, un metodo che restituisce l'ora corrente è un metodo const ma il suo valore restituito cambia tra una chiamata e l'altra.

La parola chiave const su una funzione membro contrassegna il file Questo parametro come costante.La funzione può comunque disattivare i dati globali (quindi non può essere memorizzata nella cache), ma non i dati degli oggetti (consentendo chiamate su oggetti const).

In questo contesto, a const la funzione membro significa questo this è trattato come a const anche il puntatore.In termini pratici, significa che non è consentito modificare lo stato di this all'interno di un const funzione membro.

Per le funzioni senza effetti collaterali (ovvero ciò che stai cercando di ottenere), GCC ha un "attributo funzione" chiamato pure (lo usi dicendo __attribute__((pure))): http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

Ne dubito, la funzione potrebbe ancora essere definita una funzione globale che ha alterato lo stato del mondo e non violare const.

Oltre al fatto che la funzione membro può modificare i dati globali, è possibile che la funzione membro modifichi i membri mutabili esplicitamente dichiarati dell'oggetto in questione.

Corey ha ragione, ma tieni presente che tutte le variabili membro contrassegnate come mutevole Potere essere modificato nelle funzioni membro const.

Significa anche che queste funzioni possono essere chiamate da altre funzioni const o tramite altri riferimenti const.


Modificare:Accidenti, è stato battuto di 9 secondi....9!!!:)

I metodi const possono anche modificare le localizzazioni statiche.Ad esempio, quanto segue è perfettamente legale (e chiamate ripetute a bar() restituiranno valori crescenti, non uno 0 memorizzato nella cache):

class Foo
{
public:
    int bar() const
    {
        static int x = 0;
        return x++;
    }
};
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top