Hiểu được mục đích của đặc điểm này đòi hỏi phải hiểu sự khác biệt giữa biểu diễn giá trị "đối tượng" và "biểu diễn đối tượng" của đối tượng. Từ tiêu chuẩn:
Các đối tượng đại diện của một đối tượng kiểu T
là dãy gồm N đối tượng unsigned char đưa lên bởi các đối tượng kiểu T
, trong đó N bằng sizeof(T)
. Biểu diễn giá trị của đối tượng là tập hợp các bit giữ giá trị loại T
. Đối với các kiểu có thể sao chép một cách trivially, biểu diễn giá trị là một tập hợp các bit trong biểu diễn đối tượng xác định một giá trị, là một phần tử rời rạc của một tập các giá trị được xác định.
Vì vậy, đại diện đối tượng là tổng dung lượng của một đối tượng. Nhưng hãy xem xét các đối tượng sau:
struct T
{
char c;
int i;
};
Trên nhiều hệ thống, sizeof(T)
sẽ là 8. Tại sao? Vì int
phải được căn chỉnh 4 byte nên trình biên dịch chèn 3 byte đệm giữa c
và i
. Vì ba byte đó là một phần của bộ nhớ của đối tượng (dựa trên sizeof(T)
), chúng là một phần của biểu diễn đối tượng của đối tượng.
Nhưng ba byte đó là không phải một phần của biểu diễn giá trị của nó. Nếu bạn đã sửa đổi các byte đó, chúng sẽ không ảnh hưởng đến các giá trị của c
hoặc i
hoặc bất kỳ điều gì khác về chúng.
Nếu bạn đã viết quá tải operator==
cho T
, các thay đổi đối với các byte đó sẽ không ảnh hưởng đến kết quả của nó. Mà cũng có nghĩa là nếu bạn đã viết một tình trạng quá tải operator==
, nó không thể được thực hiện như thế này:
bool operator==(const T &lhs, const T &rhs)
{
return std::memcmp(&lhs, &rhs, sizeof(T)) == 0;
}
Tại sao không? Vì hai số T
s có thể có các giá trị khác nhau cho các byte đệm đó, nhưng vẫn có cùng giá trị là c
và i
. Và do đó họ có cùng một giá trị đại diện và do đó nên được coi là tương đương.
has_unique_object_representations
là đúng khi đại diện đối tượng của T
và đại diện giá trị của nó chính xác chồng lên nhau (và khi T
là có thể sao chép được). Vì vậy, khi nào bạn sẽ quan tâm đến điều này?
Bạn có thể viết hàm băm tổng quát hoạt động trên bất kỳ loại có thể sao chép được một cách trivially T
bằng cách đọc biểu diễn giá trị của nó dưới dạng một mảng byte và băm chúng. Vâng, bạn có thể làm điều đó, nhưng chỉ khi loại không có byte đệm.Và đó là những gì has_unique_object_representations
cho bạn biết: rằng tất cả các byte trong vấn đề đại diện đối tượng.
Ngoài ra, lưu ý rằng float
loại, sẽ không nhất thiết phải có giá trị này là đúng, vì bình đẳng nhị phân và dấu phẩy động ngang không giống với IEEE-754. Vì vậy, các loại có chứa float
s cũng sẽ không nhất thiết phải có điều này là đúng sự thật. Thật vậy, việc triển khai sử dụng các số nguyên đã được bổ sung của một người, hoặc các số nguyên đã ký với các biểu diễn bẫy, cũng sẽ không có điều này đúng đối với các loại đó.
Từ ngữ ở đây http://en.cppreference.com/w/cpp/types/has_unique_object_representations ngụ ý T cần phải được trivially có thể sao chép và cũng đưa ra một số lý do. –
Các phao tương thích IEEE 754 là một ví dụ, vì các biểu diễn của các số 0 dương và âm khác nhau, nhưng các giá trị của chúng rõ ràng là bằng nhau. – Fanael
Ngoài ra, bất kỳ loại nào có nhiều bit đệm tổng số không bằng 0. – Fanael