Атрибут C++: no_unique_address (начиная с C++20)
Позволяет этому члену данных перекрываться с другими нестатическими членами данных или подобъектами базовых классов своего класса.
Синтаксис
[[no_unique_address]] |
Пояснение
Применяется к объявляемому имени при объявлении нестатического члена данных, который не является битовым полем.
Делает этот подобъект-член потенциально перекрывающимся, то есть позволяет этому члену перекрываться с другими нестатическими членами данных или подобъектами базовых классов своего класса. Это означает, что если член имеет пустой тип класса (например, безсостоянийный распределитель), компилятор может оптимизировать его так, чтобы он не занимал места, как если бы он был пустым базовым классом. Если член не является пустым, его хвостовое дополнение также может быть повторно использовано для хранения других членов данных.
Примечания
[[no_unique_address]] игнорируется MSVC даже в режиме C++20; вместо него предусмотрен [[msvc::no_unique_address]].
Пример
#include <boost/type_index.hpp>
#include <iostream>
struct Empty {}; // The size of any object of empty class type is at least 1
static_assert(sizeof(Empty) >= 1);
struct X
{
int i;
Empty e; // At least one more byte is needed to give ‘e’ a unique address
};
static_assert(sizeof(X) >= sizeof(int) + 1);
struct Y
{
int i;
[[no_unique_address]] Empty e; // Empty member optimized out
};
static_assert(sizeof(Y) >= sizeof(int));
struct Z
{
char c;
// 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’.
[[no_unique_address]] Empty e1, e2;
};
static_assert(sizeof(Z) >= 2);
struct W
{
char c[2];
// e1 and e2 cannot have the same address, but one of
// them can share with c[0] and the other with 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 Атрибут отсутствия уникального адреса [dcl.attr.nouniqueaddr]
- Стандарт C++20 (ISO/IEC 14882:2020):
- 9.12.10 Атрибут отсутствия уникального адреса [dcl.attr.nouniqueaddr]
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/attributes/no_unique_address