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)
|
Permite que este miembro de datos se superponga con otros miembros de datos no estáticos o subobjetos de clase base de su clase.
Contenidos |
Sintaxis
[
[
no_unique_address
]
]
|
|||||||||
Explicación
Se aplica al nombre que se declara en la declaración de un miembro de datos no estático que no es un campo de bits.
Hace que este subobjeto miembro sea potencialmente-superpuesto , es decir, permite que este miembro se superponga con otros miembros de datos no estáticos o subobjetos de clase base de su clase. Esto significa que si el miembro tiene un tipo de clase vacío (por ejemplo, un asignador sin estado), el compilador puede optimizarlo para que no ocupe espacio, al igual que si fuera una base vacía . Si el miembro no está vacío, cualquier relleno final en él también puede reutilizarse para almacenar otros miembros de datos.
Notas
[ [ no_unique_address ] ] es ignorado por MSVC incluso en modo C++20; en su lugar, [ [ msvc :: no_unique_address ] ] es proporcionado.
Ejemplo
#include <boost/type_index.hpp> #include <iostream> struct Empty {}; // El tamaño de cualquier objeto de tipo clase vacía es al menos 1 static_assert(sizeof(Empty) >= 1); struct X { int i; Empty e; // Se necesita al menos un byte más para dar a 'e' una dirección única }; static_assert(sizeof(X) >= sizeof(int) + 1); struct Y { int i; [[no_unique_address]] Empty e; // Miembro vacío optimizado }; static_assert(sizeof(Y) >= sizeof(int)); struct Z { char c; // e1 y e2 no pueden compartir la misma dirección porque tienen el // mismo tipo, aunque estén marcados con [[no_unique_address]]. // Sin embargo, cualquiera puede compartir dirección con 'c'. [[no_unique_address]] Empty e1, e2; }; static_assert(sizeof(Z) >= 2); struct W { char c[2]; // e1 y e2 no pueden tener la misma dirección, pero uno de // ellos puede compartir con c[0] y el otro con c[1]: [[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>(); }
Salida posible:
sizeof(Empty) == 1 sizeof(int) == 4 sizeof(X) == 8 sizeof(Y) == 4 sizeof(Z) == 2 sizeof(W) == 3
Referencias
- Estándar C++23 (ISO/IEC 14882:2024):
-
- 9.12.11 Atributo sin dirección única [dcl.attr.nouniqueaddr]
- Estándar C++20 (ISO/IEC 14882:2020):
-
- 9.12.10 Atributo sin dirección única [dcl.attr.nouniqueaddr]