为什么const类成员必须是静态的才能进行适当的优化
Why must const class members be static to be properly optimised?
给定:
class Foo { const int x = 5; public: inline int get() { return x; } };
class Bar { static const int x = 5; public: inline int get() { return x; } };
int fn0(Foo& f) { return f.get(); }
int fn1(Bar& b) { return b.get(); }
编译后的输出提供了一个内存提取来读取fn0()
中x
的值,而添加static
会导致文本5
在fn1()
中内联。这意味着,只有当整数常量是静态的时,get()
的调用方才能被优化,就好像它使用常量代替get()
一样。
我有更复杂的情况,static
不合适。派生类通过构造函数将x
初始化为不同的值;但是对于这些类中的每一个,x
是常数,并且这些类方法可以被优化,就像前面的static
的情况一样,如果仅get()
被评估为真常数的话。
事实上,我最常见的情况是初始化基类中的引用:
class Foo { int& x; public: Foo(int& init) : x(init) {} inline int get() { return x; } };
class Bar : public Foo { int m; public: Bar() : Foo(m) {} inline int getget() { return get(); };
int fn1(Bar& b) { return b.getget(); }
这里,如果get()
直接评估为getget()
内的Bar::m
,则我将避免指针间接级别。如果x
是静态的,则这是不可能的。
我不清楚为什么static
有必要进行这种优化。
类中初始化的static const int
成员是一个真正的常量表达式,即编译时常量。
非静态const int
成员在初始化后不能更改,但编译器更难静态地确定它只能有一个可能的值。请注意,只有当非静态数据成员没有mem初始值设定项时,才使用该成员的大括号或相等初始值设定值。这意味着,例如,如果你有这个:
class Foo {
const int x = 5;
public:
inline int get() { return x; }
Foo() = default;
Foo(int x) : x(x) {}
};
如果调用默认构造函数,则Foo::x
可以是5
,或者如果调用Foo::Foo(int)
,则它可以是其他东西。还要考虑如果成员被公开会发生什么:
class Foo {
public:
const int x = 5;
inline int get() { return x; }
};
现在可以使用聚合初始化:
Foo f {42};
// f.x is 42
在您编写的Foo
的特定情况下,我相信Foo::x
只能是5
,但编译器要确定这一点并不像Foo::x
是静态数据成员那样容易。编译器实现者很可能根本就不想写这样的优化。
相关文章:
- C++编译器是否优化了顺序静态变量读取?
- 未使用的C++未优化的静态成员函数/变量
- 如何使用 GCC 编译器优化创建静态库?
- GCC:在调试构建中优化的静态数据成员
- 静态 constexpr 的编译器优化
- 静态局部变量会被错误地优化吗?
- 具有必要副作用的静态初始化被优化掉了
- 线程上下文上的静态存储对象优化
- 使用LTO静态链接的可执行文件(链接时间优化):如何使用以前构建的库进行制作
- 如何防止优化静态常量
- 有没有办法强制c++编译器不优化静态库中的特定静态对象
- 静态函数编译器优化C++
- 了解工厂方法和静态变量赋值的返回值优化 (Visual Studio)
- 如何避免 C++ 编译器优化器删除静态变量代码
- 如果一个类不是直接从main中使用的,但有一个静态私有成员,那么在编译和链接时,可以使用最大优化来忽略它吗
- 编译器是否足够聪明,可以优化成员与静态方法参数相同的函子
- 未在类中使用const静态变量优化出来
- 静态初始化器在库中会被优化掉
- G++ 4.9 上静态 constexpr 的未定义引用,没有优化
- 编译器会优化出静态函数未使用的参数吗?