xml*_*lmx 5 c++ performance standards c++20 c++-attributes
#include <iostream>
struct Empty {}; // empty class
struct W
{
char c[2];
[[no_unique_address]] Empty e1, e2;
};
int main()
{
std::cout << std::boolalpha;
// e1 and e2 cannot have the same address, but one of them can share with
// c[0] and the other with c[1]
std::cout << "sizeof(W) == 2 is " << (sizeof(W) == 2) << '\n';
}
Run Code Online (Sandbox Code Playgroud)
文档说输出可能是:
sizeof(W) == 2 为真
然而,gcc 和 clang 的输出如下:
sizeof(W) == 2 为 false
如何处理是实现定义的 [[no_unique_address]]?
请参阅[intro.object]/8:
对象具有非零大小,如果...否则,如果该对象是标准布局类类型的基类子对象,没有非静态数据成员,则它的大小为零。否则,对象大小为零的情况是由实现定义的。
C++11 中的标准布局类必须进行空基类优化(请参阅此处进行讨论)。空成员优化从来都不是强制性的。正如您所怀疑的,它是实现定义的。
是的,几乎所有方面no_unique_address都是由实现定义的。它是一个允许优化的工具,而不是强制优化的工具。
话虽如此,no_unique_address当您尝试拥有两个具有相同 type 的子对象时,您永远不应该假设它会起作用。该标准仍然要求同一类型的所有不同子对象具有不同的地址,no_unique_address或者不具有不同的地址。虽然编译器有可能通过从根本上重新排序成员来为这些空子对象分配不同的地址......但他们几乎不会这样做。
合理利用优化的最佳选择no_unique_address是永远不要有两个相同类型的子对象,并尝试将所有可能为空的成员放在前面。也就是说,您应该期望实现将空no_unique_address成员分配给下一个成员的偏移量(或整个包含结构的偏移量)。