编译器是否会优化返回具有固定大小数组的结构的函数?

假设我在C/C++中有一个具有固定大小的数组成员的struct,例如:

#define SIZE 10000
struct foo{
  int vector_i[SIZE];
  float vector_f[SIZE];
};

我想创建一个函数,该函数将返回foo的实例,如下所示:

foo func(int value_i, float value_f){
  int i;
  foo f;
  for(i=0;i<SIZE;i++) f.vector_i[i] = value_i;
  for(i=0;i<SIZE;i++) f.vector_f[i] = value_f;
  return f;
}

如果我使用:

调用函数
foo ff = func(1,1.1);

编译器是否会执行某种优化(即总拥有成本)?

可执行文件是直接填充ff变量,还是先填充func中的f,然后复制fff中的所有值?

如何检查是否执行了优化?


解决方案

我的答案适用于C++。

编译器是否会执行某种优化(即总拥有成本)?

您所说的TCO是指"尾部呼叫优化"吗?该函数不会在末尾进行函数调用(如果愿意,可以称为尾部调用),因此不会应用优化。

由于命名返回值优化,编译器可以elide将返回值复制到临时。还可以避免从临时数据库进行复制初始化。


如何检查是否执行了优化?

通过读取生成的汇编代码。

如果您不能读取程序集,另一种方法是添加有副作用的复制和移动构造函数,并观察这些副作用是否发生。但是,修改程序可能会影响编译器是否决定进行优化(但不需要副作用来防止复制遗漏)。


如果不想依赖优化,则应通过引用(c中的指针)将退出对象显式传递给函数,并就地修改它。


复制删除的标准参考[class.copy] §31 (current standard draft)

当满足某些条件时,允许实现省略类对象的复制/移动构造,即使为复制/移动操作选择的构造函数和/或对象的析构函数具有副作用。[...]

本节介绍了在本例中满足的条件。该报价是根据2016-04-07年4月4日的标准文件草稿生成的。不同版本的标准文件的编号可能会有所不同,规则也略有变化。引用部分自c++03起一直未更改,其中部分为[类.副本]§15。

相关文章