構造体を参照渡しすることはなぜ一般的な最適化ではないのでしょうか? 質問する

構造体を参照渡しすることはなぜ一般的な最適化ではないのでしょうか? 質問する

今日まで、私は、適切なコンパイラは、構造体が十分に大きく、後者の方が高速な場合、構造体の値渡しを参照渡しに自動的に変換すると思っていました。私の知る限り、これは考えるまでもない最適化のように思えます。しかし、これが実際に起こるかどうかという好奇心を満たすために、C++とC++の両方で簡単なテストケースを作成しました。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私の疑問は、なぜこのようなものが、実際にすべてのs をスタックにプッシュするのではなく、参照渡しにコンパイラによって最適化されないのかということです。

注: 使用されるコンパイラ スイッチ: GCC -O2 (-O3 inlined foo().)、DMD -O -inline -release。

編集: 当然のことながら、一般的なケースでは、コピー コンストラクターが関係している場合や、元の構造体が呼び出し先で変更されている場合など、値渡しと参照渡しのセマンティクスは同じではありません。ただし、実際のシナリオの多くでは、観察可能な動作の点ではセマンティクスは同一になります。私が尋ねているのは、これらのケースです。

ベストアンサー1

C/C++ では、コンパイラが関数宣言のみに基づいて関数の呼び出しをコンパイルできる必要があることを忘れないでください。

呼び出し元がその情報のみを使用する可能性があることを考えると、コンパイラが関数をコンパイルして、あなたが言及している最適化を活用する方法はありません。呼び出し元は関数が何も変更しないことを知ることができないため、参照渡しはできません。一部の呼び出し元は詳細情報が不足しているために値渡しする可能性があるため、関数は値渡しを前提としてコンパイルする必要があり、誰もが値渡しする必要があります。

パラメータを ' const' としてマークした場合でも、関数が const 性を破棄する可能性があるため、コンパイラは最適化を実行できないことに注意してください (渡されるオブジェクトが実際に const でない限り、これは許可され、明確に定義されています)。

静的関数 (または匿名名前空間内の関数) の場合、関数に外部リンクがないため、コンパイラはあなたが言及している最適化を実行できる可能性があります。関数のアドレスが他のルーチンに渡されたり、ポインタに格納されたりしない限り、他のコードから呼び出すことはできません。この場合、コンパイラはすべての呼び出し元を完全に把握できるため、最適化を実行できると思います。

何かがそうであるかどうかはわかりません (実際、あまり頻繁に適用できない可能性が高いため、何かがそうであるとしたら驚きます)。

もちろん、プログラマーは (C++ を使用する場合)、const&可能な場合はいつでもパラメーターを使用してコンパイラーにこの最適化を強制的に実行させることができます。なぜコンパイラーが自動的に実行できないのかと疑問に思うかもしれませんが、これが次善策だと思います。

おすすめ記事