C++ 使用静态类成员而不是私有字段之间的速度差异是什么?
我正在编写一个应用程序,其中包含静态配置类:C++ 使用静态类成员而不是私有字段之间的速度差异是什么?,c++,C++,我正在编写一个应用程序,其中包含静态配置类: class Device { public: static Device &getInstance() { static Device instance; return instance; } private: Device() { init(); } void init() { this->ramps_count = 30
class Device {
public:
static Device &getInstance() {
static Device instance;
return instance;
}
private:
Device() {
init();
}
void init() {
this->ramps_count = 300;
this->gates = 64;
}
public:
Device ( Device const & ) = delete;
void operator= ( Device const & ) = delete;
int ramps_count;
int gates;
};
此类用于获取和设置我的设备配置。当然,这个类中还有其他字段。对我来说,它是静态的非常重要,因为我在很多地方使用这些字段,这样使用它很方便。此外,我还具有将此配置保存到/从文件加载的功能
另一方面,我有一个类经常使用这种配置。我的应用程序有一个调用此类的主循环:
class FrameFFTProcessor : public FrameProcessor {
public:
FrameFFTProcessor (){
}
void process ( ) {
for(int i=0; i<Device::getInstance().ramps_count; i++){
for(int i=0; i<Device::getInstance().gates; i++){
//... doint it's job
// and somethimes using values
// Device::getInstance().ramps_count and gates
}
}
}
private:
};
class FrameFFTProcessor:public FrameProcessor{
公众:
FrameFFTProcessor(){
}
无效过程(){
对于(inti=0;iramps\u count=Device::getInstance().ramps\u count;
这->门=设备::getInstance().gates;
}
无效过程(){
对于(int i=0;i如果您的程序是单线程的,那么第一个方法似乎更快,因为您不需要花费时间将整个资源复制到类对象,而只需要直接访问变量。编译器通常会优化getter函数,让调用者直接访问变量这取决于您的缓存使用情况
如果你的访问在内存中紧密相连,系统可以缓存它们。如果它们分散,它必须从内存芯片中获取,这是最昂贵的原子操作——我们说的是比缓存访问慢十倍
通过将字段设置为静态,可以将它们放在单独的内存区域中。但这可能会帮助或阻碍缓存,具体取决于缓存决定如何填充自身。不建议将静态配置值存储为其他类(配置类除外)的成员。类(例如,FrameProcessor
)应该保留与其相关的数据,而不是其他任何内容。您可以在process
方法中获取Device
配置类的引用/指针,并使用数据值
void process ( )
{
const Device& devConfig = Device::getInstance();
for(int i=0; i<devConfig.ramps_count; i++){
for(int i=0; i<devConfig.gates; i++){
...
void进程()
{
const Device&devConfig=Device::getInstance();
对于(inti=0;i访问类的成员或单例的成员具有几乎相同的间接级别,您应该将目标放在局部变量上,以几乎强制编译器使用寄存器
我认为一个可以保持最佳速度而不必将设备内部值存储在处理器对象中的解决方案(正如其他人所说,这是一件不好的事情)是……倒计时:
void process() {
int i = Device::getInstance().ramps_count;
for(;i > 0; --i){
int j = Device::getInstance().gatesl;
for(; j > 0; --j){
//... doint it's job
// and somethimes using values
// Device::getInstance().ramps_count and gates
}
}
}
这也是因为检查一个值(假定在寄存器中不同于零)不需要内存访问,而检查它不同于非常量值则需要内存访问(缓存访问也比不访问慢)
这不是我发明的,很多绘图算法都是这么做的
还请注意为访问者构建const方法,即:
class Device {
[...]
public:
int getGateSL() const { return gatesl; }
int getRampCounts() const { return ramp_count; }
[...]
}
因为编译器的优化器可以在const方法上做更积极的工作。这两个方法不同,因为第二个是单例值的快照(这些值可以不同步)。静态值需要一个单例。如果init确实使用编译时常量,则只需使用静态成员或类的单个全局实例即可。如果编写访问方法,则向编译器提供constexpr作为提示(如果只返回微不足道的值,则通常不需要此选项。如果没有此选项,优化器将看到此选项)。使用单例可以在每次访问时检查对象是否存在。这会花费时间,而这对您的设计毫无用处。
class Device {
[...]
public:
int getGateSL() const { return gatesl; }
int getRampCounts() const { return ramp_count; }
[...]
}