Il significato di 'const' è ancora thread-safe in C ++ 11?

2

Recentemente ho trovato il video di Herb Sutter da su come il significato di const e mutable è cambiato in C ++ 11 per significare bitwise const (e thread-safe , di conseguenza) anziché tradizionale logicamente const.

Cinque anni dopo, i programmatori hanno migrato a questo nuovo significato di const?

Ho provato a usarlo mentre scrivevo una nuova applicazione, ma sembra che stia marcando ogni membro privato come mutabile perché sono protetti da un mutex o thread-safe (dalla loro implementazione) - che non sentirsi bene (sono inesperto e non ho una base per questo).

È buona norma progettare un'applicazione thread-safe per contrassegnare ogni funzione membro const e ogni variabile membro mutable ?

    
posta CK. 05.10.2018 - 22:00
fonte

2 risposte

7

Il video che hai citato è per un pubblico avanzato ed esperto. Herb Sutter cerca di portare questo pubblico a un consenso su come migliorare comunicare l'intento di queste parole chiave ad altre persone, in questa età di tutto ciò che desidera essere thread-safe .

Quindi non aspettarti che questo video contenga tutto il necessario per scrivere codice perfettamente thread-safe.

I'm marking every private member as mutable because they're either protected by a mutex or thread-safe (by their implementation) - which doesn't feel right (I'm inexperienced and do not have a basis for this).

Ecco un esempio ipotetico di ciò che sarebbe palesemente sbagliato:

class Size
{
    mutable int x;
    mutable int y;
    // ...
public:
    void setSize(int newX, int newY) const // (first scream)
    {
        // modify members "x" and "y", "SAFELY!" (second scream)
    }
};

La firma della funzione urla in modo errato, perché una funzione chiamata setSize non potrebbe essere const . L'implementazione del codice della funzione alla fine richiederebbe di contrassegnare i membri "x" e "y" come mutable , il che farebbe anche gridare male.

Non importa quale codice è nella funzione setSize . Se il nome della funzione implica che la funzione cambierà lo stato dell'oggetto, non dovrebbe essere contrassegnato con const . Supponiamo di rimuovere la parola chiave const dalla funzione. Ora scopriamo che non dobbiamo usare la parola chiave mutable sui membri "x" e "y". Problema risolto.

In altre parole, se l'uso di const e mutable sono entrambi contro l'intuizione, e se tale uso imbarazzante si verifica in coppia, allora si dovrebbe essere sospettosi del fatto che il loro uso sia sbagliato.

Tuttavia, il video menziona un caso eccezionale. Se una classe contiene un membro std::mutex , è quasi sempre corretto contrassegnarlo come membro mutable . Si prega di fare riferimento al video per le spiegazioni.

Una volta che hai fatto esperienza nel farlo correttamente, puoi fare affidamento sul tuo intuito per vedere se sembra naturale e naturale significa correggere.

Se il nome di una funzione implica che non dovrebbe cambiare lo stato dell'oggetto, allora dovrebbe essere contrassegnato con const , e il codice all'interno deve essere fatto thread-safe, con non che eseguono operazioni thread-safe.

Questa è la mentalità espressa nel video collegato sopra. Quando si tratta di sicurezza del thread, gli utenti del tuo codice (te stesso o i tuoi compagni di squadra) hanno certe aspettative che alcune funzioni non dovrebbero fare certe cose .

Il video menziona questi esempi:

  • bool operator == (const T& other) const non dovrebbe mai modificare this o other , perché nessuno si aspetterebbe confronti per modificare qualcosa. (Questo è chiamato "effetto collaterale".)
  • class T { public: T(const T& other) {...} }; non dovrebbe mai modificare other , perché la stessa istanza di other potrebbe essere stata passata in due thread, ogni threading lo ha passato al costruttore di copie.

Che ne dici di questo codice?

class Size
{
    const int x;
    const int y;
    // ...
public:
    Size(int init_x, int init_y)
        : x(init_x), y(init_y)
    {
    }
};

Questo codice è ancora migliore. Dimostra l'uso corretto di const sui membri.

Tuttavia, impedisce a uno di utilizzare la classe Size in determinati modi. Ad esempio, non puoi utilizzare gli operatori di assegnazione per sovrascrivere un'istanza esistente di Size . In altre parole, seguendo la best practice quando si implementa la classe Size , potrebbe essere necessario ridisegnare un altro codice sorgente che utilizza Size . Questo è il "problema contagioso" che rende costanza un'importante considerazione per un progetto C ++.

    
risposta data 06.10.2018 - 10:46
fonte
6

Is it good practice while designing a thread-safe application to mark every member function const and every member variable mutable?

No, questa è non buona pratica.

Una funzione membro const segnala che la funzione non modificherà l'oggetto su cui è chiamato. Poiché l'oggetto non verrà modificato, è possibile chiamare la funzione da più thread senza il blocco esterno.

Tuttavia, non è il caso che le funzioni membro const siano le uniche funzioni thread-safe. Qualsiasi altra funzione può essere protetta da thread.
Usare il modificatore const per contrassegnare una funzione mutante poiché thread-safe sta dando il segnale sbagliato.

    
risposta data 06.10.2018 - 10:46
fonte

Leggi altre domande sui tag