performance - 为什么通过引用传递结构不是常见的优化?

标签 performance optimization compiler-construction assembly struct

直到今天,我一直认为,如果结构足够大以至于后者会更快,那么不错的编译器会自动将结构传递值转换为传递引用。据我所知,这似乎是最明智的选择。但是,为了满足我对这种情况是否真的发生的好奇心,我在C++和D中创建了一个简单的测试用例,并查看了GCC和Digital Mars D的输出。两者都坚持在传递所有值时传递32字节结构有问题的函数所做的是将成员加起来并返回值,而无需传入传入的结构。C++版本如下。

#include "iostream.h"

struct S {
    int i, j, k, l, m, n, o, p;
};

int foo(S s) {
    return s.i + s.j + s.k + s.l + s.m + s.n + s.o + s.p;
}

int main() {
    S s;
    int bar = foo(s);
    cout << bar;
}

我的问题是,为什么编译器不会优化这种类似的东西以传递引用,而不是将所有这些int实际压入堆栈?

注意:使用的编译器开关:GCC -O2(-O3内联foo()。),DMD -O -inline -release。

编辑:显然,在一般情况下,按值传递与按引用传递的语义将是不同的,例如,如果涉及复制构造函数,或者在被调用方中修改了原始结构,则该语义是相同的。但是,在许多现实情况下,语义在可观察到的行为方面都是相同的。这些是我要问的情况。

最佳答案

不要忘记,在C / C++中,编译器仅需要能够基于函数声明来编译对函数的调用。

由于调用者可能仅使用该信息,因此编译器无法编译该函数以利用您正在谈论的优化。调用者不知道该函数不会修改任何内容,因此它不能被ref传递。由于某些调用者可能由于缺少详细信息而按值传递,因此必须在假定传递值的情况下编译函数,并且每个人都需要按值传递。

请注意,即使您将参数标记为“const”,编译器仍然无法执行优化,因为该函数可能在说谎并舍弃了constness(只要传入对象,就可以允许并定义良好)实际上不是const)。

我认为对于静态函数(或匿名命名空间中的函数),编译器可能会进行您正在讨论的优化,因为该函数没有外部链接。只要函数的地址没有传递给其他例程或存储在指针中,就不应从其他代码中调用它。在这种情况下,编译器可以完全了解所有调用者,因此我想它可以进行优化。

我不确定是否可以这样做(实际上,如果可以这样做,我会感到很惊讶,因为它可能无法经常应用)。

当然,作为程序员(使用C++时),您可以通过使用const&参数强制编译器执行此优化。我知道您在问为什么编译器无法自动执行此操作,但是我想这是下一个最好的选择。

关于performance - 为什么通过引用传递结构不是常见的优化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/552134/

相关文章:

mysql - 为什么 MySQL 使用错误的索引?

c# - 我可以强制编译器优化特定方法吗?

c++ - 继续C Syntax Analyzer相关项目的困惑

c# - 我可以给编译器/JIT 什么优化提示?

c++ - gcc 不合并连续的栅栏

c++ - 英特尔 C++ 编译器错误? (指针别名)

java - 如何测量 OpenCL 读出时间?

java - 如何真正对 Java 应用程序的内存使用情况进行基准测试

MySql 唯一索引与索引速度

sql - 在 Postgres 中将时间戳截断为 5 分钟的最快方法是什么?