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)
|
Позволяет этому члену данных перекрываться с другими нестатическими членами данных или подобъектами базовых классов его класса.
Содержание |
Синтаксис
[
[
no_unique_address
]
]
|
|||||||||
Объяснение
Применяется к имени, объявляемому в объявлении нестатического члена данных, который не является битовым полем.
Делает этот член-подобъект потенциально-перекрывающимся , то есть позволяет этому члену перекрываться с другими нестатическими членами данных или подобъектами базовых классов его класса. Это означает, что если член имеет пустой тип класса (например, аллокатор без состояния), компилятор может оптимизировать его так, чтобы он не занимал места, как если бы он был пустым базовым классом . Если член не пуст, любое конечное заполнение в нем также может быть повторно использовано для хранения других членов данных.
Примечания
[ [ no_unique_address ] ] игнорируется MSVC даже в режиме C++20; вместо этого предоставляется [ [ msvc :: no_unique_address ] ]
Пример
#include <boost/type_index.hpp> #include <iostream> struct Empty {}; // Размер любого объекта пустого класса не менее 1 static_assert(sizeof(Empty) >= 1); struct X { int i; Empty e; // Требуется как минимум один дополнительный байт для уникального адреса 'e' }; static_assert(sizeof(X) >= sizeof(int) + 1); struct Y { int i; [[no_unique_address]] Empty e; // Пустой член оптимизирован }; static_assert(sizeof(Y) >= sizeof(int)); struct Z { char c; // e1 и e2 не могут иметь одинаковый адрес, потому что они имеют // одинаковый тип, даже если они помечены [[no_unique_address]]. // Однако любой из них может разделять адрес с 'c'. [[no_unique_address]] Empty e1, e2; }; static_assert(sizeof(Z) >= 2); struct W { char c[2]; // e1 и e2 не могут иметь одинаковый адрес, но один из // них может разделять с c[0], а другой с 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>(); }
Возможный вывод:
sizeof(Empty) == 1 sizeof(int) == 4 sizeof(X) == 8 sizeof(Y) == 4 sizeof(Z) == 2 sizeof(W) == 3
Ссылки
- Стандарт C++23 (ISO/IEC 14882:2024):
-
- 9.12.11 Атрибут no unique address [dcl.attr.nouniqueaddr]
- Стандарт C++20 (ISO/IEC 14882:2020):
-
- 9.12.10 Атрибут no unique address [dcl.attr.nouniqueaddr]