Mat*_* M. 15 c++ compiler-optimization
在C++中,大多数优化都是从as-if规则派生的.也就是说,只要程序表现得如果没有进行优化,那么它们就是有效的.
空基优化就是这样一个技巧:在某些情况下,如果基类为空(没有任何非静态数据成员),则编译器可能会忽略其内存表示.
显然,似乎标准禁止对数据成员进行优化,即使数据成员为空,它仍然必须至少占用一个字节的位置:来自n3225,[class]
4 - 类类型的完整对象和成员子对象应具有非零大小.
注意:这导致在Policy Design中使用私有继承,以便在适当的时候启动EBO
我想知道,使用as-if规则,是否仍然可以执行此优化.
编辑:遵循一些答案和评论,并使我更清楚我想知道的.
首先,让我举一个例子:
struct Empty {};
struct Foo { Empty e; int i; };
Run Code Online (Sandbox Code Playgroud)
我的问题是,为什么sizeof(Foo) != sizeof(int)?特别是,除非你指定一些打包,否则很可能是因为对齐问题Foo将是int的两倍,这似乎是荒谬的夸大其词.
注意:我的问题不是原因sizeof(Foo) != 0,EBO实际上也不需要这样做
根据C++,这是因为没有子对象可能具有零大小.但是,基础被授权为零大小(EBO)因此:
struct Bar: Empty { int i; };
Run Code Online (Sandbox Code Playgroud)
很可能(感谢EBO)服从sizeof(Bar) == sizeof(int).
Steve Jessop似乎认为没有两个子对象具有相同的地址.我考虑过它,但在大多数情况下它实际上并没有阻止优化:
如果你有"未使用"的内存,那么它是微不足道的:
struct UnusedPadding { Empty e; Empty f; double d; int i; };
// chances are that the layout will leave some memory after int
Run Code Online (Sandbox Code Playgroud)
但事实上,它甚至比那更"糟糕",因为Empty空间永远不会被写入(如果EBO开始......你最好不要这样做),因此你实际上可以把它放在一个不是另一个地址的占用地方宾语:
struct Virtual { virtual ~Virtual() {} Empty e; Empty f; int i; };
// most compilers will reserve some space for a virtual pointer!
Run Code Online (Sandbox Code Playgroud)
或者,即使在我们原来的情况下:
struct Foo { Empty e; int i; }; // deja vu!
Run Code Online (Sandbox Code Playgroud)
(char*)foo.e == (char*)foo.i + 1如果我们想要的只是不同的地址,那就可能有.
它即将使用该[[no_unique_address]]属性进入 c++20 。
template<typename Key, typename Value, typename Hash, typename Pred, typename Allocator>
class hash_map {
[[no_unique_address]] Hash hasher;
[[no_unique_address]] Pred pred;
[[no_unique_address]] Allocator alloc;
Bucket *buckets;
// ...
public:
// ...
};
Run Code Online (Sandbox Code Playgroud)
在as-if规则下:
struct A {
EmptyThing x;
int y;
};
A a;
assert((void*)&(a.x) != (void*)&(a.y));
Run Code Online (Sandbox Code Playgroud)
不得触发断言.因此x,当你只需要在结构中添加填充时,我没有看到秘密制作大小为0的任何好处.
我认为理论上编译器可以跟踪是否可以将指针带到成员,并且只有在它们肯定不是时才进行优化.这将是有限的用途,因为有两个不同版本的结构具有不同的布局:一个用于优化的情况,一个用于通用代码.
但是,例如,如果您在堆栈上创建A的实例,并使用完全内联(或优化器可见)的内容执行某些操作,是的,可以完全省略结构的某些部分.这不是特定于空对象的 - 空对象只是对象的特殊情况,其存储不被访问,因此在某些情况下根本不会被分配.
| 归档时间: |
|
| 查看次数: |
1714 次 |
| 最近记录: |