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
]
]
|
|||||||||
설명
비트 필드가 아닌 비정적 데이터 멤버의 선언에서 선언되는 이름에 적용됩니다.
이 멤버 서브오브젝트를 potentially-overlapping (잠재적으로 중첩 가능)하게 만듭니다. 즉, 이 멤버가 자신의 클래스의 다른 비정적 데이터 멤버나 베이스 클래스 서브오브젝트와 중첩될 수 있도록 허용합니다. 이는 멤버가 빈 클래스 타입(예: 상태 없는 할당자)을 가질 경우, 컴파일러가 empty base (빈 베이스)와 마찬가지로 공간을 차지하지 않도록 최적화할 수 있음을 의미합니다. 멤버가 비어 있지 않은 경우, 해당 멤버의 테일 패딩(tail padding)도 다른 데이터 멤버를 저장하는 데 재사용될 수 있습니다.
참고 사항
[ [ 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 고유 주소 없음 속성 [dcl.attr.nouniqueaddr]
- C++20 표준(ISO/IEC 14882:2020):
-
- 9.12.10 No unique address 속성 [dcl.attr.nouniqueaddr]