Namensräume
Varianten
Aktionen

C++ Attribut: no_unique_address (seit C++20)

Von cppreference.com
< cpp‎ | language‎ | attributes
 
 
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
 
 
Attribute
(C++23)
(C++11)(bis C++26)
(C++14)
(C++20)
(C++17)
(C++11)
no_unique_address
(C++20)
(C++20)
 

Ermöglicht diesem Datenmember, mit anderen nicht-statischen Datenmembern oder Basisklassen-Subobjekten seiner Klasse überlappt zu werden.

Inhalt

[bearbeiten] Syntax

[[no_unique_address]]

[bearbeiten] Erklärung

Gilt für den Namen, der in der Deklaration eines nicht-statischen Datenmembers deklariert wird, der kein Bit-Feld ist.

Macht dieses Member-Subobjekt potenziell überlappend, d.h. es erlaubt diesem Member, sich mit anderen nicht-statischen Datenmembern oder Basisklassen-Subobjekten seiner Klasse zu überlappen. Das bedeutet, wenn der Member einen leeren Klassentyp hat (z.B. einen zustandslosen Allokator), kann der Compiler ihn so optimieren, dass er keinen Speicherplatz einnimmt, ähnlich wie bei einer leeren Basisklasse. Wenn der Member nicht leer ist, können eventuelle Füllbytes am Ende wiederverwendet werden, um andere Datenmember zu speichern.

[bearbeiten] Hinweise

[[no_unique_address]] wird von MSVC auch im C++20-Modus ignoriert; stattdessen wird [[msvc::no_unique_address]] bereitgestellt.

[bearbeiten] Beispiel

#include <iostream>
 
struct Empty {}; // empty class
 
struct X
{
    int i;
    Empty e;
};
 
struct Y
{
    int i;
    [[no_unique_address]] Empty e;
};
 
struct Z
{
    char c;
    [[no_unique_address]] Empty e1, e2;
};
 
struct W
{
    char c[2];
    [[no_unique_address]] Empty e1, e2;
};
 
int main()
{
    // the size of any object of empty class type is at least 1
    static_assert(sizeof(Empty) >= 1);
 
    // at least one more byte is needed to give e a unique address
    static_assert(sizeof(X) >= sizeof(int) + 1);
 
    // empty member optimized out
    std::cout << "sizeof(Y) == sizeof(int) is " << std::boolalpha 
              << (sizeof(Y) == sizeof(int)) << '\n';
 
    // e1 and e2 cannot share the same address because they have the
    // same type, even though they are marked with [[no_unique_address]]. 
    // However, either may share address with c.
    static_assert(sizeof(Z) >= 2);
 
    // e1 and e2 cannot have the same address, but one of them can share with
    // c[0] and the other with c[1]
    std::cout << "sizeof(W) == 2 is " << (sizeof(W) == 2) << '\n';
}

Mögliche Ausgabe

sizeof(Y) == sizeof(int) is true
sizeof(W) == 2 is true

[bearbeiten] Referenzen

  • C++23 Standard (ISO/IEC 14882:2024)
  • 9.12.11 No unique address attribute [dcl.attr.nouniqueaddr]
  • C++20 Standard (ISO/IEC 14882:2020)
  • 9.12.10 No unique address attribute [dcl.attr.nouniqueaddr]