2016-03-31 8 views
6

Es scheint, als ob die volatile Vergleichsfunktionen in shared_ptr Implementierung nicht existieren.In C++ - ist es möglich, volatile shared_ptr mit nullptr zu vergleichen?

Macht es überhaupt Sinn zu existieren?

+5

Beachten Sie, dass 'volatile' kein tragbarer Thread-Synchronisationsmechanismus ist (obwohl dies in manchen Umgebungen möglicherweise ausreichend ist).' volati le 'wird normalerweise in Verbindung mit speicherabgebildeten I/O und ähnlichen Mechanismen verwendet, was ein seltsamer Ort für ein 'shared_ptr' wäre. Vielleicht solltest du klären, warum du einen flüchtigen shared_ptr haben würdest. – peterchen

+3

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

+0

@MikeVine: Ausgezeichnet! Ich muss mich an diesen Link erinnern.(Und überprüfen Sie es täglich, falls es sich ändert) – peterchen

Antwort

4

Im Wesentlichen nicht, der Standard berücksichtigt nicht comparisons oder boolean conversion auf einem volatile shared_ptr.

Die following fails zu kompilieren ...

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

Sie können die volatile off werfen (über. Ein const_cast), aber ich bin mir nicht sicher, dass das gewünschte Ergebnis. Vom cppreference:

Ändern ein const Objekt durch einen nicht const Zugriffspfad und unter Bezugnahme auf ein volatile Objekt durch ein nicht volatile glvalue Ergebnis in undefiniertem Verhalten.

Ganz allgemein, in nicht Mitglied Methoden wie volatile Kennzeichnung wird die Klasse oder Bibliothek Implementierer effektiv sagen „dies nicht die Verwendung als volatile Objekt soll sein“ - wenn es dann den entsprechenden Methoden oder Überladungen würden für volatile Objekte sorgen. Ebenso gilt dies für const, Mitglieder als const Markierung, werden sie sagen: „Diese Klasse kann als const Objekt verwendet werden.

Warum die volatile benötigt wird, welche externen Quellen die shared_ptr werden könnte modifizieren“ ohne Wissen der Compiler "(dies ist einer der Verwendungen von volatile)? Wenn Threading-Probleme, dann wäre es besser, mit einem der Thread-Bibliothek-Dienstprogramme gedient, oder wenn die Anforderung einfach Optimierungen ausschalten, haben verschiedene Compiler Mechanismen dafür bereits (pragmas usw.).

+0

Guter Punkt, obwohl ich glaube, dass std :: atomic über flüchtig mit C++ 11 ist, wenn wir tatsächlich über Threading sprechen. – Atifm

3

Volatile ist nur ein Hinweis für den Compiler, dass der Speicher möglicherweise unerwartet geändert wird. Deaktiviert einige Optimierungen. Unter den Deckeln ist es nur eine Speicheradresse.

Der gemeinsame Zeiger hält nur die Ressource. Da jedoch std :: shared_ptr :: get() nicht als flüchtig gekennzeichnet ist, können Sie nicht wirklich einen shared_ptr verwenden, um einen flüchtigen Zeiger auf eine zugängliche Weise zu verwalten.

Ich würde empfehlen, einen nackten Zeiger zu verwenden, und mit dem Zielbereich oder dem Zerstörer, um danach aufzuräumen.

Wenn Sie volatile verwenden, da der Zeiger möglicherweise von einem anderen Thread geändert wird, sollten Sie std :: atomic anstelle von volatile verwenden. In Threading-Workflows wurden vor std::atomic Zeiger, auf die von anderen Threads aus zugegriffen wurde, normalerweise als flüchtig markiert. Das ist keine bewährte Methode mehr.

+0

eigentlich flüchtig ist kein Vorschlag. Eine der Sachen, die es tut, ist: Jeder Zugriff (Lese- oder Schreiboperation, Elementfunktionsaufruf, etc.) auf dem flüchtigen Objekt wird als ein sichtbarer Nebeneffekt für die Zwecke der Optimierung behandelt (das heißt innerhalb eines einzelnen Threads von Ausführung, flüchtige Zugriffe können nicht nachbestellt oder optimiert werden – NathanOliver

+1

Da diese Funktion keinen flüchtigen Qualifier hat, ist es unmöglich, sie mit einem flüchtigen Objekt zu bezeichnen ... – cpplearner

+0

@nathanLiver hat es so umformuliert, wie Sie es vorgeschlagen haben – Atifm