C++ attribute: no_unique_address (since C++20)
| General topics | ||||||||||||||||
| Flow control | ||||||||||||||||
| Conditional execution statements | ||||||||||||||||
| Iteration statements (loops) | ||||||||||||||||
|
||||||||||||||||
| Jump statements | ||||||||||||||||
| Functions | ||||||||||||||||
| Function declaration | ||||||||||||||||
| Lambda function expression | ||||||||||||||||
inline
specifier
|
||||||||||||||||
| Dynamic exception specifications ( until C++17* ) | ||||||||||||||||
noexcept
specifier
(C++11)
|
||||||||||||||||
| Exceptions | ||||||||||||||||
| Namespaces | ||||||||||||||||
| Types | ||||||||||||||||
| Specifiers | ||||||||||||||||
|
||||||||||||||||
| Storage duration specifiers | ||||||||||||||||
| Initialization | ||||||||||||||||
| Expressions | ||||||||||||||||
| Alternative representations | ||||||||||||||||
| Literals | ||||||||||||||||
| Boolean - Integer - Floating-point | ||||||||||||||||
| Character - String - nullptr (C++11) | ||||||||||||||||
| User-defined (C++11) | ||||||||||||||||
| Utilities | ||||||||||||||||
| Attributes (C++11) | ||||||||||||||||
| Types | ||||||||||||||||
typedef
declaration
|
||||||||||||||||
| Type alias declaration (C++11) | ||||||||||||||||
| Casts | ||||||||||||||||
| Memory allocation | ||||||||||||||||
| Classes | ||||||||||||||||
| Class-specific function properties | ||||||||||||||||
|
||||||||||||||||
| Special member functions | ||||||||||||||||
|
||||||||||||||||
| Templates | ||||||||||||||||
| Miscellaneous | ||||||||||||||||
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
(C++23)
|
||||
|
(C++11)
(until C++26)
|
||||
|
(C++14)
|
||||
|
(C++17)
|
||||
|
(C++26)
|
||||
|
(C++20)
|
||||
|
(C++17)
|
||||
|
(C++17)
|
||||
|
(C++11)
|
||||
|
no_unique_address
(C++20)
|
||||
|
(TM TS)
|
||||
|
(C++20)
|
Erlaubt es diesem Datenmitglied, mit anderen nicht-statischen Datenmitgliedern oder Basisklassenunterobjekten seiner Klasse überlappt zu werden.
Inhaltsverzeichnis |
Syntax
[
[
no_unique_address
]
]
|
|||||||||
Erklärung
Gilt für den Namen, der in der Deklaration eines nicht-statischen Datenelements deklariert wird, das kein Bitfeld ist.
Macht dieses Mitgliedssubobjekt potenziell-überlappend , d.h. erlaubt es, dass dieses Mitglied mit anderen nicht-statischen Datenelementen oder Basisklassen-Subobjekten seiner Klasse überlappt werden kann. Dies bedeutet, dass wenn das Mitglied einen leeren Klassentyp hat (z.B. zustandsloser Allokator), der Compiler es so optimieren kann, dass es keinen Speicherplatz belegt, genau wie bei einer leeren Basisklasse . Wenn das Mitglied nicht leer ist, kann dessen abschließende Auffüllung ebenfalls wiederverwendet werden, um andere Datenelemente zu speichern.
Hinweise
[ [ no_unique_address ] ] wird von MSVC selbst im C++20-Modus ignoriert; stattdessen wird [ [ msvc :: no_unique_address ] ] bereitgestellt.
Beispiel
#include <boost/type_index.hpp> #include <iostream> struct Empty {}; // Die Größe eines beliebigen Objekts vom Typ einer leeren Klasse ist mindestens 1 static_assert(sizeof(Empty) >= 1); struct X { int i; Empty e; // Mindestens ein weiteres Byte wird benötigt, um 'e' eine eindeutige Adresse zu geben }; static_assert(sizeof(X) >= sizeof(int) + 1); struct Y { int i; [[no_unique_address]] Empty e; // Leeres Mitglied optimiert }; static_assert(sizeof(Y) >= sizeof(int)); struct Z { char c; // e1 und e2 können nicht dieselbe Adresse teilen, da sie denselben // Typ haben, selbst wenn sie mit [[no_unique_address]] markiert sind. // Allerdings kann jede Adresse mit 'c' teilen. [[no_unique_address]] Empty e1, e2; }; static_assert(sizeof(Z) >= 2); struct W { char c[2]; // e1 und e2 können nicht dieselbe Adresse haben, aber eines // von ihnen kann mit c[0] und das andere mit c[1] teilen: [[no_unique_address]] Empty e1, e2; }; static_assert(sizeof(W) >= 2); template <typename T> void print_size_of() { using boost::typeindex::type_id; std::cout << "sizeof(" << type_id<T>() << ") == " << sizeof(T) << '\n'; } int main() { print_size_of<Empty>(); print_size_of<int>(); print_size_of<X>(); print_size_of<Y>(); print_size_of<Z>(); print_size_of<W>(); }
Mögliche Ausgabe:
sizeof(Empty) == 1 sizeof(int) == 4 sizeof(X) == 8 sizeof(Y) == 4 sizeof(Z) == 2 sizeof(W) == 3
Referenzen
- C++23-Standard (ISO/IEC 14882:2024):
-
- 9.12.11 No-unique-address-Attribut [dcl.attr.nouniqueaddr]
- C++20-Standard (ISO/IEC 14882:2020):
-
- 9.12.10 No-unique-address-Attribut [dcl.attr.nouniqueaddr]