当使用成员超过函数变量时,在优化/速度方面有任何差异吗?

Is there any difference in optimization/speed when using member over function variable?

本文关键字:方面 速度 优化 任何差 成员 变量 函数      更新时间:2023-10-16

假设有一个用于从某个位置读取数据的类,并以不同的格式(不是线程安全的)提供它。对于它读取的每一项,它做如下操作:

TargetDataStruct HostToTargetConverter::Next()
{
  HostDataStruct source;
  sourceData->GetItem(m_index++, &source);
  TargetDataStruct target;
  target.seize = source.day;
  target.have = source.fun;
  return target;
}

在编译器的速度或可优化性方面,将HostDataStruct sourceTargetDataStruct target声明为成员变量会有什么不同吗?我的想法是,这两个结构不需要每次调用都推到堆栈上,也不需要每次都初始化。

一般来说,没有比"视情况而定"更好的答案了。

使HostDataStructTargetDataStruct成为成员所产生的差异包括;

  • 对它们的每次访问都会取消一个指针的引用。在成员内部包含类访问sourcetarget的函数分别求this->sourcethis->target(即this).
  • 如果包含对象只构造一次(例如未创建)并被反复摧毁)那么它的成员也是如此。那意味着构造的开销只发生一次(对于包含对象的每个实例),而不是每次调用函数都构造它们。
  • 在你的代码中,对象将在你的函数中被重新分配(即它的值被改变)。这是每次调用函数时的开销(并且抵消了对象构造函数只调用一次的事实)。

问题是,这些东西的成本确实各不相同。小型对象的构建和销毁成本较低,而大型对象的构建和销毁成本较高。复杂的构造函数(或析构函数)最好只构造一次对象(即使对象很小,构造函数也可能访问其他资源)。访问局部构造对象的成员是编译器可以高效实现的,而指针的解引用涉及更多的操作,因此编译器可能不会特别高效地实现。

要找出哪个选项提供更好的运行时速度,您需要进行测试——例如使用分析器。您得到的结果很可能是特定于您的编译器、主机配置等。

在你的代码中HostDataStruct &TargetDataStruct在堆栈中,所以读/写的访问是最快的。

优化删除所有不必要的操作

现在,如果你把source和target作为成员,唯一可以使你的代码更快的是,如果你的对象构造函数多次使用(通常是在构造函数中调用"new"),并且你的代码经常调用。

为了可读性,您可以创建这样的转换构造函数:

TargetDataStruct(const HostDataStruct& value);
所以你的代码将是
TargetDataStruct HostToTargetConverter::Next()
{
    HostDataStruct source;
    sourceData->GetItem(m_index++, &source);
    return TargetDataStruct(source);
}

但是你也可以避免HostDataStruct分配如果你的sourceData容器/对象保持数据存活,使你的sourceData->GetItem()返回一个常量HostDataStruct&;

const HostDataStruct& GetItem(const int p_id);

,你的代码将是这样的:

TargetDataStruct HostToTargetConverter::Next()
{
    return TargetDataStruct(sourceData->GetItem(m_index++, &source));
}

最后一个解决方案应该是最快的,避免无用的复制和对象构造。

如果你仍然需要性能,即:如果你的代码经常被调用,做以下事情:在第一次调用时,在缓存中构建TargetDataStruct,然后始终返回对缓存数据的引用。