Namensräume
Varianten
Aktionen

cv (const und volatile) Typqualifizierer

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Erscheinen in jedem Typspezifizierer, einschließlich decl-specifier-seq von Deklarationsgrammatik, um die Konstanz oder Volatilität des zu deklarierenden Objekts oder des benannten Typs anzugeben.

  • const - definiert, dass der Typ konstant ist.
  • volatile - definiert, dass der Typ volatile ist.

Inhalt

[bearbeiten] Erklärung

Jeder (möglicherweise unvollständige) Typ außer einem Funktionstyp oder Referenztyp ist ein Typ in einer Gruppe der folgenden vier unterschiedlichen, aber verwandten Typen

  • Eine cv-unqualifizierte Version.
  • Eine const-qualifizierte Version.
  • Eine volatile-qualifizierte Version.
  • Eine const-volatile-qualifizierte Version.

Diese vier Typen in derselben Gruppe haben dieselben Repräsentations- und Ausrichtungsvoraussetzungen.

Array-Typen gelten als cv-qualifiziert wie ihre Elementtypen.

[bearbeiten] const und volatile Objekte

Wenn ein Objekt erstellt wird, bestimmen die verwendeten cv-Qualifizierer (die Teil von decl-specifier-seq oder Teil eines declarator in einer Deklaration oder Teil von type-id in einem new-expression sein können) die Konstanz oder Volatilität des Objekts wie folgt:

  • Ein const-Objekt ist
  • ein Objekt, dessen Typ const-qualifiziert ist, oder
  • ein nicht-mutable-Teil eines const-Objekts.
Ein solches Objekt kann nicht modifiziert werden: Versuche, dies direkt zu tun, sind ein Kompilierungsfehler, und Versuche, dies indirekt zu tun (z. B. durch Modifikation des const-Objekts über eine Referenz oder einen Zeiger auf einen nicht-const-Typ), führen zu undefiniertem Verhalten.
  • Ein volatile-Objekt ist
  • ein Objekt, dessen Typ volatile-qualifiziert ist,
  • ein Teil eines volatile-Objekts, oder
  • ein mutable-Teil eines const-volatile-Objekts.
Jeder Zugriff (Lese- oder Schreibvorgang, Aufruf einer Memberfunktion usw.), der über einen glvalue-Ausdruck eines volatile-qualifizierten Typs erfolgt, wird für die Zwecke der Optimierung als sichtbarer Nebeneffekt behandelt (d. h., innerhalb eines einzelnen Ausführungsthreads können volatile-Zugriffe nicht herausoptimiert oder mit anderen sichtbaren Nebeneffekten, die sequenziert vor oder sequenziert nach dem volatile-Zugriff sind, neu geordnet werden. Dies macht volatile-Objekte geeignet für die Kommunikation mit einem Signalhandler, aber nicht mit einem anderen Ausführungsthread, siehe std::memory_order). Jeder Versuch, auf ein volatile-Objekt über einen glvalue eines nicht-volatile Typs zuzugreifen (z. B. über eine Referenz oder einen Zeiger auf einen nicht-volatile Typ), führt zu undefiniertem Verhalten.
  • Ein const-volatile-Objekt ist
  • ein Objekt, dessen Typ const-volatile-qualifiziert ist,
  • ein nicht-mutable-Teil eines const-volatile-Objekts,
  • ein const-Teil eines volatile-Objekts, oder
  • ein nicht-mutable-volatile-Teil eines const-Objekts.
Verhält sich sowohl als const-Objekt als auch als volatile-Objekt.

Jeder cv-Qualifizierer (const und volatile) kann in einer cv-Qualifizierer-Sequenz höchstens einmal vorkommen. Beispielsweise sind const const und volatile const volatile keine gültigen cv-Qualifizierer-Sequenzen.

[bearbeiten] mutable-Spezifizierer

  • mutable - erlaubt die Modifikation des als mutable deklarierten Klassenmembers, auch wenn das enthaltende Objekt als const deklariert ist (d. h., der Klassenmember ist mutable).

Kann in der Deklaration eines nicht-statischen Klassenmembers eines nicht-Referenz-Nicht-Const-Typs vorkommen

class X
{
    mutable const int* p; // OK
    mutable int* const q; // ill-formed
    mutable int&       r; // ill-formed
};

mutable wird verwendet, um anzugeben, dass der Member den extern sichtbaren Zustand der Klasse nicht beeinflusst (wie oft für Mutexe, Cache-Speicher, Lazy Evaluation und Zugriffs-Instrumentierung verwendet).

class ThreadsafeCounter
{
    mutable std::mutex m; // The "M&M rule": mutable and mutex go together
    int data = 0;
public:
    int get() const
    {
        std::lock_guard<std::mutex> lk(m);
        return data;
    }
 
    void inc()
    {
        std::lock_guard<std::mutex> lk(m);
        ++data;
    }
};

[bearbeiten] Konvertierungen

Es gibt eine partielle Ordnung der cv-Qualifizierer nach aufsteigenden Beschränkungen. Der Typ kann als mehr oder weniger cv-qualifiziert bezeichnet werden als

  • unqualifiziert < const
  • unqualifiziert < volatile
  • unqualifiziert < const volatile
  • const < const volatile
  • volatile < const volatile

Referenzen und Zeiger auf cv-qualifizierte Typen können implizit in Referenzen und Zeiger auf mehr cv-qualifizierte Typen konvertiert werden. Details finden Sie unter Qualifizierungskonvertierungen.

Um eine Referenz oder einen Zeiger auf einen cv-qualifizierten Typ in eine Referenz oder einen Zeiger auf einen weniger cv-qualifizierten Typ zu konvertieren, muss const_cast verwendet werden.

[bearbeiten] Hinweise

Der const-Qualifizierer, der in der Deklaration einer nicht-lokalen, nicht-volatile nicht-Template(seit C++14)nicht-inline(seit C++17)-Variable verwendet wird, die nicht als extern deklariert ist, verleiht ihr interne Bindung. Dies unterscheidet sich von C, wo const-Variablen auf Dateiebene externe Bindung haben.

Die C++-Sprachgrammatik behandelt mutable als Speicherklassen-Spezifizierer und nicht als Typqualifizierer, aber es beeinflusst weder die Speicherklasse noch die Bindung.

Einige Verwendungen von volatile sind veraltet

(seit C++20)

[bearbeiten] Schlüsselwörter

const, volatile, mutable

[bearbeiten] Beispiel

#include <cstdlib>
 
int main()
{
    int n1 = 0;          // non-const object
    const int n2 = 0;    // const object
    int const n3 = 0;    // const object (same as n2)
    volatile int n4 = 0; // volatile object
 
    const struct
    {
        int n1;
        mutable int n2;
    } x = {0, 0};        // const object with mutable member
 
    n1 = 1;   // OK: modifiable object
//  n2 = 2;   // error: non-modifiable object
    n4 = 3;   // OK: treated as a side-effect
//  x.n1 = 4; // error: member of a const object is const
    x.n2 = 4; // OK: mutable member of a const object isn't const
 
    const int& r1 = n1; // reference to const bound to non-const object
//  r1 = 2; // error: attempt to modify through reference to const
    const_cast<int&>(r1) = 2; // OK: modifies non-const object n1
 
    const int& r2 = n2; // reference to const bound to const object
//  r2 = 2; // error: attempt to modify through reference to const
//  const_cast<int&>(r2) = 2; // undefined behavior: attempt to modify const object n2
 
    [](...){}(n3, n4, x, r2); // see also: [[maybe_unused]]
 
    std::system("g++ -O3 -Wa,-adhln ./main.cpp"); // may issue asm on POSIX systems
}

Mögliche Ausgabe

# typical machine code produced on an x86_64 platform
# (only the code that contributes to observable side-effects is emitted)
main:
    movl    $0, -4(%rsp) # volatile int n4 = 0;
    movl    $3, -4(%rsp) # n4 = 3;
    xorl    %eax, %eax   # return 0 (implicit)
    ret

[bearbeiten] Defect reports

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
CWG 1428 C++98 die Definition von 'const-Objekt' basierte auf der Deklaration basierend auf dem Objekttyp
CWG 1528 C++98 es gab keine Anforderung an die Anzahl der Vorkommen
jedes cv-Qualifizierers in derselben cv-Qualifizierer-Sequenz
höchstens einmal für
jeden cv-Qualifizierer
CWG 1799 C++98 mutable konnte auf Datenmember angewendet werden, die nicht deklariert wurden
const, aber die Typen der Member konnten immer noch const-qualifiziert sein
kann mutable nicht auf Daten anwenden
Member von const-qualifizierten Typen

[bearbeiten] Siehe auch

C-Dokumentation für const-Qualifizierer
C-Dokumentation für volatile-Qualifizierer