当前位置:  开发笔记 > 编程语言 > 正文

为什么不通过引用传递struct一个常见的优化?

如何解决《为什么不通过引用传递struct一个常见的优化?》经验,为你挑选了3个好方法。

直到今天,我一直认为正确的编译器会自动将struct pass-by-value转换为pass-by-reference,如果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.

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



1> Michael Burr..:

不要忘记,在C/C++中,编译器需要能够仅根据函数声明编译对函数的调用.

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

请注意,即使您将参数标记为' const',编译器仍然无法执行优化,因为该函数可能是撒谎并抛弃了常量(只要传入的对象是允许的,这是允许的和定义良好的实际上不是const).

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

我不确定是否有(实际上,如果有的话,我会感到惊讶,因为它可能不经常应用).

当然,作为程序员(使用C++时),您可以强制编译器const&尽可能使用参数来执行此优化.我知道你在问为什么编译器不能自动完成,但我想这是下一个最好的事情.



2> JaredPar..:

问题是你要求编译器做出关于用户代码意图的决定.也许我希望我的超大型结构可以通过值传递,这样我就可以在复制构造函数中执行某些操作.相信我,那里有人有一些他们有效地需要在复制构造函数中调用这样的场景.切换到ref将绕过复制构造函数.

将此作为编译器生成的决策将是一个坏主意.原因是它无法推断代码的流动.你不能看电话,知道它究竟会做什么.你必须a)知道代码和b)猜测编译器优化.



3> Edmund..:

一个答案是编译器需要检测被调用的方法不会以任何方式修改结构的内容.如果确实如此,那么通过引用传递的效果将与传递值的效果不同.


您可以为此类结构采用写时复制语义.
推荐阅读
帆侮听我悄悄说星星
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有