7

ここに C++ で次のコードがあります。

#include <iostream>

int main(int argc, const char * argv[])
{
    goto line2;
line1:
    std::cout << "line 1";
    goto line3;
line2:
    std::cout << "line 2";
    goto line1;
line3:
    std::cout << "line 3";
    goto line4;
line4:
    std::cout << "Hello, World!\n";
    return 0;
}

たとえば 10,000 行のコードのより大きなプログラムを作成し、自分で作成した関数を使用しないことに決めた場合、goto ステートメントのみを使用します。グローバル変数のみを使用します。私はベストプラクティスに関しては少し正気ではありませんが、それは非常に特定の目的のためです。問題は、これは goto ステートメントで飛び回るのに効率的かということです。goto ラベルが 1000 個ある場合はどうなりますか?

goto ステートメントは、別のメモリ アドレスにジャンプするようにコンピュータに指示するマシン コードに直接変換されますか? これは、関数を呼び出すコストと比較して、このようにジャンプするマシンのコストが低いですか?

いくつかの計算を実行するための非常に効率的なプログラムを作成したいので知りたいのですが、アセンブリ/マシン コードに頼らずに非常に効率的である必要があります。


これはメンテナンス、コードのわかりやすさ、ベストプラクティスの点で悪い考えだと言う必要はありません。私はそれをよく知っています。質問への回答が欲しいだけです。関数呼び出しを使用するのが良いのか、goto を使用するのが良いのかについての議論はしたくありません。


質問を明確にするために、関数を使用する従来のプログラムと比較して、10,000 行のプログラムでのみ gotos を使用する場合がどうなるかについて懸念しています。これら 2 つのプログラムを比較対照するには、複数の方法があります。たとえば、CPU キャッシュはどのように実行されるでしょうか。関数呼び出しなしでどのような節約ができるでしょうか。通常、CPU キャッシュはスタックを近くに保持するため、コール スタックがなければ、これが CPU キャッシュにどのような影響を与えるでしょうか。そのため、キャッシュが正しく使用されていないためにパフォーマンスが低下する可能性がある場合があります。時間効率の観点から、ジャンプと比較した場合の関数呼び出しの実際のコストはいくらですか。2 つのスタイルのプログラミングを効率的に比較対照する方法はたくさんあります。

4

6 に答える 6

29

goto ステートメントは、別のメモリ アドレスにジャンプするようにコンピュータに指示するマシン コードに直接変換されますか?

はい。

これは、関数を呼び出すコストと比較して、このようにジャンプするマシンのコストが低いですか?

はい。

ただし、コンパイラが関数呼び出しを認識した場合、関数を呼び出すためのコードを実際に生成する必要はありません。関数の根性を取り、ジャンプではなく、呼び出しがあった場所にそれらを貼り付けることができます。したがって、関数を呼び出す方が効率的です。

さらに、コードが小さいほど、CPU キャッシュに収まる可能性が高くなるため、(一般的に言えば) より効率的になります。コンパイラはこれを見て、関数が小さい場合はインライン化する方がよいか、大きい場合は分離して実際の関数にする方がよいかを判断して、最速のコードを生成します (生成するように設定している場合)。最速のコード)。あなたはこれを見ることができないので、あなたは推測し、おそらく間違っていると思います.

そして、それらは明らかなもののほんの一部です。コンパイラが実行できる最適化は他にもたくさんあります。コンパイラに決定させます。それはあなたより賢いです。私より賢いです。コンパイラはすべてを知っています。真剣に、Cthulhu はおそらくコンパイラです。

あなたはそうしないと言っていましたが、私はそれを言うつもりです.これを行うことを決定する前に、あなたのコードをプロファイリングすることを強くお勧めします.あなたの時間の価値がないことはほぼ保証できます. コンパイラ (ほとんどが AI レベルに近いスマート) は、通常の関数呼び出しと同じかそれ以上の速度のコードをおそらく生成できます。メンテナンスの側面は言うまでもありません。

于 2013-01-07T05:22:29.713 に答える
16

goto ステートメントは、別のメモリ アドレスにジャンプするようにコンピュータに指示するマシン コードに直接変換されますか?

かなり。

これは、関数を呼び出すコストと比較して、このようにジャンプするマシンのコストが低いですか?

関数呼び出しは非常によく似たジャンプを行いますが、ジャンプを行う前に、新しい関数の新しいスタック フレームを設定し、呼び出し規約に従ってパラメーターをプッシュし、最後にリターンを設定する必要があります。価値とくつろぎ。はい、おそらくこれを行わない方が速いでしょう。

私は少し狂っている

はい。

于 2013-01-07T05:21:53.850 に答える
4

1)問題は、これは goto ステートメントでジャンプするのに効率的でしょうか? goto ラベルが 1000 個ある場合はどうなりますか?

前後gotoにジャンプする4つのラベルを持つ小さな例から、パフォーマンスの点で効率的ではありません。関数呼び出しメカニズムのオーバーヘッドを回避するために、このメソッドは、コンパイラが自動的に行う他の多くの最適化を無効にしています。私はそれらをリストしていませんが、これは読む価値があります。

2) goto ステートメントは、別のメモリ アドレスにジャンプするようにコンピュータに指示するマシン コードに直接変換されますか?

はい(他の人が正しく指摘したように)

3)関数を呼び出すコストと比較して、このようにジャンプするマシンのコストは低いですか?

はい、コンパイラが以前のものであり、最適化メカニズムが組み込まれていない場合のみ。そうでなければいいえ。

そして、私はベストプラクティスについて話しているのではありません..

于 2013-01-07T05:58:49.263 に答える
3

はい、goto から生成されたマシン コードはストレート JUMP になります。そして、スタックに対して何もする必要がないため、これはおそらく関数呼び出しよりも高速です (ただし、渡す変数のない呼び出しは、同じように高速になるように最適化されます)。

そして、このコードで何かがうまくいかないときは、神があなたを助けてくださいます. または、他の誰かがそれを維持しなければならないとき。

于 2013-01-07T05:23:43.210 に答える
2

クエリに正確に答えるのは難しいです。プログラムの複雑さと内部での goto ステートメントの使用に依存します。

goto ステートメントは、無条件ジャンプ命令 (例: jmp ) と同等です。goto のスコープはファイル内になります。

Ritchie は、goto ステートメントの使用を避けることを提案しています。それでも goto ステートメントを使用したい/使用しなければならない場合は、トップダウン アプローチで使用し、ボトムアップ アプローチでは使用しないでください。

さて、これらは教科書の詳細です。

実際には、goto ステートメントを使用する場所と goto jump の後にプログラム フローがどこにあるかを十分に確認する必要があります。そうしないと、1000 の goto ステートメントで述べたように、プログラム フローを決定することも難しくなり、他のことを忘れてしまいます。したがって、プログラムをさらに改善することは非常に困難です。

このような問題を回避するために、ループ、条件ステートメント、break および continue ステートメント、関数など、他にも多くの機能があります。

それが役に立てば幸い.....

于 2013-01-07T05:34:33.200 に答える
0

要するに、「GoTo」ステートメントは効率的ですが、それが実際の使用方法です。Herbert Schildt によると ( C++ from the GROUND UP)、「goto ステートメントの使用を必要とするプログラミング状況はありません。これは、言語を完成させるために必要な項目ではありません。」最終的に、多くのプログラマーがステートメントを嫌う主な理由は、goto ステートメントがコードを混乱させたり、コードを非常に読みにくくしたりする傾向があるためです。そうは言っても、goto ステートメントが混乱を減らし、コードをより効率的にすることができる場合もありますが、それは使用方法と使用されるコンテキストに完全に依存します。個人的には、関数呼び出しを使用することをお勧めします。 、いくつかの goto ステートメントとは対照的に。他の人は同意しないかもしれません。

于 2013-01-07T05:25:04.570 に答える