2016-03-31 36 views
6

Sembra che le funzioni di confronto volatile nell'implementazione shared_ptr non esistano.In C++ - è possibile confrontare volatile shared_ptr in nullptr?

Ha senso esistere?

+5

Si noti che 'volatile' non è un meccanismo di sincronizzazione del thread portatile (anche se probabilmente in alcuni ambienti potrebbe essere sufficiente). di solito viene usato in congiunzione con I/O mappato in memoria e meccanismi simili, che sarebbe un posto strano per un 'shared_ptr'. Forse dovresti chiarire * perché * avresti una volatile shared_ptr. – peterchen

+3

@peterchen http://cxx.isvolatileusefulwiththreads.com/ –

+0

@MikeVine: Eccellente! Devo ricordare quel collegamento.(E controllalo ogni giorno, nel caso cambi) – peterchen

risposta

4

In sostanza no, lo standard non soddisfa comparisons o boolean conversion su un volatile shared_ptr.

La following fails per compilare ...

auto main() -> int { 
    volatile shared_ptr<int> a; 
    if (a == nullptr) // fails 
     ; // empty 
    if (a) // fails 
     ; // empty 
} 

Si potrebbe lanciare l'volatile off (tramite. Un const_cast), ma non sono sicuro che avrà il risultato desiderato. Dalla cppreference:

Modifica di un oggetto const attraverso un percorso non const accesso e facendo riferimento a un oggetto volatile attraverso un volatile risultato non glvalue comportamento indefinito.

In termini più generali, in non metodi di marcatura membri come volatile, gli implementatori classe o libreria sono effettivamente dicendo "questo non è destinato ad essere utilizzato come un oggetto volatile" - se lo fosse, allora i metodi appropriati o sovraccarichi fornirebbe oggetti volatile. Allo stesso modo, questo vale per const, nella marcatura membri come const, che stanno dicendo "questa classe può essere utilizzato come un oggetto const.

Perché è il volatile necessari, quali fonti esterne potrebbe essere la modifica del shared_ptr" senza la conoscenza di il compilatore "(questo è uno degli usi di volatile)? Se ci sono problemi di thread, allora sarebbe meglio servire con una delle utilità della libreria di thread, o se il requisito è semplicemente disattivare le ottimizzazioni, vari compilatori hanno meccanismi per questo già (pragma ecc.)

+0

Un buon punto, anche se credo che l'uso di std :: atomic sia perfettabile rispetto a volatile con C++ 11 se stiamo parlando di threading. – Atifm

3

Volatile è solo un'indicazione al compilatore che la memoria potrebbe cambiare in modo imprevisto. Disattiva alcune ottimizzazioni. Sotto le coperte è solo un indirizzo di memoria.

Il puntatore condiviso sta semplicemente tenendo/gestendo la risorsa. Detto questo, dato che std :: shared_ptr :: get() non è marcato volatile, non si può veramente usare un shared_ptr per gestire un puntatore volatile in modo accessibile.

Si consiglia di utilizzare un puntatore nudo e di utilizzare l'uscita con ambito o il distruttore per pulire dopo.

Se si utilizza volatile perché il puntatore può essere modificato da un altro thread, è possibile prendere in considerazione l'utilizzo di std :: atomic anziché volatile. Nei flussi di lavoro di threading, prima di std::atomic, i puntatori a cui si accede da altri thread erano in genere contrassegnati come volatili. Non è più la pratica migliore.

+0

effettivamente volatile non è un suggerimento. Una delle cose che fa è: Ogni accesso (operazione di lettura o scrittura, chiamata funzione membro, ecc.) Sull'oggetto volatile viene considerato come un effetto collaterale visibile ai fini dell'ottimizzazione (ovvero, all'interno di una singola discussione di esecuzione, gli accessi volatili non possono essere riordinati o ottimizzati – NathanOliver

+1

Poiché tale funzione non ha un qualificatore volatile, è impossibile chiamarla con un oggetto volatile .... – cpplearner

+0

@nathanOliver lo ha riformulato come suggerito. – Atifm