ループの後ろで変数を宣言するのか、ループの中で宣言するのか?

 
   string st = "";
   for (int i = 0; i < 1000; i++)
   {
      st = i;
      ...
   }

または

   for (int i = 0; i < 1000; i++)
   {
      string st = i;
      ...
   }

mql5コンパイラの最適化を考えると、違いがあるのでしょうか?

 
pivalexander:

または

mql5コンパイラの最適化を考えると、違いがあるのでしょうか?

コンパイルに差はありませんので、2番目の選択肢を自由に使ってください。
 

個人的には、前者の方が好きです。

念のため。コンパイラは賢いので毎回メモリを確保しないのかもしれませんが、最初の場合は明示的に指定しますが、2番目の場合はブロックの中に変数を作り、ブロックから抜けるときに削除するという言語の論理なので、コンパイラの暗黙の結果になっています。

また、変換せずにintとstringを同一視するのは悪手です。

 
pivalexander:

mql5コンパイラの最適化を考えると、違いがあるのでしょうか?

違いがないとは聞きません。最初のオプションだけを使用する、違いがあります。mclのdisassmは勉強してないですけどね。

 
Georgiy Merts:

個人的には、前者の方が好きです。

念のため。コンパイラは賢いので毎回メモリを確保しないのかもしれませんが、最初の場合は明示的に指定しますが、2番目の場合はブロックの中に変数を作り、そのブロックを抜けるときに削除しなければならないという言語の論理なので、コンパイラの暗黙の結果になっています。

また、変換せずにintとstringを同一視するのは悪手です。

ジョージの言う通り、保証はされない。

そして、「数値」から「文字列」への暗黙の変換のゆがみが発生するのです。


そして、これこそが、不確定性やゆがみを解消する方法なのです。

for (int i = 0; i < 1000; i++)
   {
      static string st = IntegerToString(i);
      ...
   }
 
Georgiy Merts:

個人的には、前者の方が好きです。

念のため。コンパイラは賢いので毎回メモリを確保しないかもしれないが、最初のケースでは私が明示的に指定したが、2番目のケースではコンパイラの作業の暗黙の結果であったということだ

コンパイラにとっては些細なことなので、何も言うことはありません。 それを気にするあまり、アセンブラでコーディングすればいいのでは? もっとも、それすらも今では無意味になっていますが。 最近のコンパイラの最適化に勝つには、相当努力しなければならないでしょう。

p.s. ここでは文字列バッファの 話をしているので、些細なことで少し興奮したのかもしれません。しかし、MQLではループ内だけでなく、関数呼び出しの間でも保存されることが保証されています。この話題は一度ならずここで取り上げられた
 

聞いてはいけません、ここでいろいろと教えてくれます ))

// c++
#include <iostream>
#include <string>
using namespace std;

void* operator new(size_t sz) {
    void *ptr = std::malloc(sz);
    if (ptr)
        return ptr;
    else
        throw std::bad_alloc{};
}


int main() {
        for (uint i = 0;  i < 3;  ++ i) {
                string s;
                char buf[10];
                sprintf(buf, "%u", i);
                s = "sfjhidfsrtea111";
                s += buf;
                cout << s << '\n';
        }
}

gcc -O3をコンパイルし、デバッガで実行し、operator newでブレークポイントを 設定すると、3つのコールが発生します。clangも同様です。

注:文字列がループから取り出された場合、私は1回呼び出しを受ける。

 
Alexey Navoykov:

冗談じゃない、コンパイラにとってそんなことは些細なことなのだ。 そんなに偏執的なら、純粋にアセンブラでコードを書けばよいだろう。 しかし、それすら最近は無意味になってきている。 最近のコンパイラの最適化に勝つためには、努力しなければならないのだ。

p.s.文字列バッファの 場合の些細なことに少し興奮したのかもしれません。しかし、MQLではループ内だけでなく、関数呼び出しの間でも保存されることが保証されています。この話題は一度ならずここで取り上げられた

いいえ、そうではありません。

もちろん、この場合、通常のコンパイラは、ループ内の変数宣言をループ外に置かなければならない。

ただ、常にコンパイラーを信頼し、自分自身を信頼するべきだと思います。ローカル変数は宣言されたときに作成され、宣言されたブロックが終了したときに削除されるのがコンパイラの標準である。ですから、コンパイラがあなたのためにコードを改善してくれるのを待つのではなく、そもそもこの原則に注目すべきなのです。

コドベースのソースコードを見ていると、単純で小さいけれども潜在的に危険な欠陥がいかに多いか、よく考えさせられます。この場合、まだそれほど致命的な問題ではなく、プログラムの動作が少し遅くなる程度です。 実際のエラーはもっと厄介かもしれません。

 
Vict:

聞いてはいけません、ここでいろいろと教えてくれます ))

gcc -O3をコンパイルし、デバッガで実行し、operator newでブレークポイントを設定すると、3つのコールが発生します。clangも同様です。

したがって、文字列がループから外れると、1回だけ呼び出されることになる。

あなた自身がブレークポイントによって最適化を妨害したのですから、そうしなければできなかったのです。 最適化の本質は、アルゴリズムのロジックを変えてはいけないということなのです。だから明示的に検出できないのです。 そこにブレークポイントがあれば、当然、コンパイラーはこのコードをカットする権利はありません。 コンパイラーがブレーク ポイントを飛び越えられるとでも思ったのでしょうか。)

最適化は、コードのコンパイルや性能測定によって初めて検出できるものなので、まずそれを行うべきでしょう。そして落ち着く )

 
測定待ち)
 
Alexey Navoykov:

そうしないとできないのは、あなた自身がブレークポイントによる最適化を邪魔しているからです。 最適化のポイントは、アルゴリズムのロジックを変えてはいけないということです。だから明示的に検出できないのです。 そこにブレークポイントがあれば、コンパイラは当然このコードをカットする権利はありません。 コンパイラがブレークポイントを飛び越えるかもしれないと予想していたのですか?)

最適化は、コードのコンパイルや性能測定によって初めて検出できるものなので、まずそれを行うべきでしょう。そして落ち着く )

おいおい、それは野暮だぞ、何をコメントするんだ、デバッガの仕組みを完全に誤解してるじゃないか。

速度について - メモリマネージャは非常にダムではなく、それがOSに要求されるという事実ではなく、以前に割り当てられたを使いすぎることがあります。一般的には、使い方はあなた次第です。しかし、少なくとも具体的な証拠を提示するまでは、他人を納得させるべきではありません、どこにあるのでしょうか?

理由: