さようならロボット - こんにちはマラスムス - ページ 8

 
simpleton:

ローカル変数とパラメータは同じスコープにあるので、 - パラメータの名前がこの名前でもローカル変数でも関係ありませんが、どちらにしてもこの名前は外部スコープで名前を隠します。

どんな場合でもダメです。変数が参照渡しされる場合、ローカルコピーは作成されず、渡された変数に対して直接作業が行われます。では、どのような隠し事があるのでしょうか?
 
Andrei01:
どの機能でもない。参照渡しの場合、ローカルコピーは作成されず、渡された変数に対して直接演算が行われる。で、どういう隠し方をしているかというと、 。

そこで行われるのが「名前隠し」です。コピー、コピーでないもの、その他はすべて二の次です。関数内部で、参照名を使用した場合、その参照が参照するオブジェクトに対して作業が行われます。アウタースコープにあるオブジェクトを参照する場合は、そのオブジェクトを対象に作業を行う。これは、名前の隠蔽がないからではなく、他のケースと同様に隠蔽は存在するのですが、参照がこのオブジェクトを指しているからです。関数はこのように呼ばれる。まさにこのオブジェクトを参照で渡し、現在それを指している。別のオブジェクトを呼び出した瞬間に渡すと、同じ関数コードが別のオブジェクトで動作します。

私は、型名と変数名、つまりできるだけ性質の異なる実体を例に挙げ、隠蔽は名前に適用/参照され、それ以外は二の次であることを示したかったのです。

しかし、このテーマでMQL4++で別の例を作ろうとしたとき、偶然にもMQL4++ではパラメータに追加のスコープが作成されることを発見しました。ローカル変数のスコープが すでにネストしている。

#property strict

void f(int a) {
  int saved = a;
  int a = a + 1;

  Print("saved = " , saved, ", a = ", a);
}

void OnStart() {
  f(3);
}

この例は、特徴的な警告を含むCOMPILEDです。

declaration of 'a' hides local declaration at line 3    3.mq4   5       7

そして、後にそれが正常に実行される。

23:52:22 Script 3 EURUSDm,H1: loaded successfully
23:52:22 3 EURUSDm,H1: initialized
23:52:22 3 EURUSDm,H1: saved = 3, a = 4
23:52:22 3 EURUSDm,H1: uninit reason 0
23:52:22 Script 3 EURUSDm,H1: removed

MQL4+では、パラメータに対して別の「層」のスコープが作られていることは明らかです。このため、パラメータと同じ名前のローカル変数を宣言することが可能です。

C/C++では、そのような「層」は存在しない。

void f(int a) {
  int saved = a;
  int a = a + 1;
}

コンパイラは、その名前の変数がすでにスコープ内に存在すると俗に説明する。

$ icpc -c 1.cpp
1.cpp(3): error: "a" has already been declared in the current scope
    int a = a + 1;
        ^

つまり、関数のパラメータとそのローカル変数のスコープが同じである。

なぜMQL4+ではそうなっていないのか、どういう目的でそうなっていないのか、それはもちろん興味深い問題ですが...。

 
simpleton:

void f(int a)

この例では、特徴的な警告が表示された状態でCOMPILESしています。

このケースは、ローカルコピーの作成ではなく、変数の参照渡しと誤った警告の場合について述べています。

void f(int& a)
 

最初の数記事しか読んでないけど。

もちろん、マットの下でもなかなかうまくはいきません。ここでは、エンドユーザーの手元に届く製品のテストに、開発者の怠慢がある。しかし、MT4も多通貨戦略(テスト)には弱く、ニーズがあり、改良が必要です。だから、やっぱりいつかはそうなってほしいですね。

プログラミングが苦手な人は、本番に行かず、とりあえずデモを利用する。相変わらずダンスが下手な人は、金やピンクなどの「玉」の邪魔をするんですね。

がんばってください。


 
Andrei01:

これは、ローカルコピーを作成せず、変数を参照渡しして誤った警告を出した場合です。

void f(int& a)

警告の内容については、特に問題ではありません。さらに、参照渡しか値渡しかだけでなく、その変数がどのような型であるかも重要ではありません。

#property strict

int a; // line 3
class A { };
void f(A *&a) { } // line 5
void OnStart() { }

コードがコンパイルされ、あなたが議論している警告が生成されます。

declaration of 'a' hides global declaration at line 3   3.mq4   5       12

なぜかそれを理解しようとしない。

この警告自体はまったく間違いではありません。しかも、MQL4+のスコープトラッキングは、ぱっと見、他のやり方と比べても驚くほどよくできています。

警告は、事実であっても実用的ではなく、それでいて消せない--そういうことなのです。そして、決してリンクの送信ではありません。

 
simpleton:

警告の内容という点では、これは関係ない。さらに、変数が参照渡しであるか値渡しであるかは関係ない

変数そのものを渡して関数内で変更するのと、変数そのものはそのままで、コピーを作成するのとでは、警告の本質に大きな違いがあるのです。

また、警告を無効化したり、カスタマイズすることができないのは、三菱商事独自の古典的なスタイルである「させない」ことです:)))どうしようもないことですが、このスタイルが宗教的な属性に昇華されてしまっているので、謙虚に、おとなしく受け入れるしかないのです...。ここに論理や正義を求める意味はない。))

 

ううううううううううううううううううううううううううううううううううううううううう メチャクチャに働いています。

全く不満はありません。

 
simpleton:

潜在的なエラーは、あくまでも潜在的なエラーであって、必ずしもエラーであるとは限りません。したがって、「これらのエラーを修正しなければならないということだ」という発言は誤りです。

...

この人たちはオタクなんです。このような馬鹿は、コンパイラが味方 であることを理解せずに、風車のようにコンパイラと戦っているのです。安全でない可能性のあるコード断片に対してコンパイラが悪態をついたら、喜びましょう。起動直後にエラー文字列が表示されてアプリケーションがクラッシュしても大丈夫です。しかし、エラーや警告がなく、プログラムがうまく動いているように見えても、時々、原因がどこにも追跡できないような奇妙な不具合が発生し、手に負えないコードになることは、神様が許してくれないのです。そんなとき、「ポインタが不正 です」とか「ゼロ除算です」といったエラーを夢想して、水蒸気にまみれてしまうのです。
 
C-4:
しかし、エラーも警告もなく、プログラムはうまく動いているように見えるのに、時々奇妙なバグが発生し、その原因がどこにも見つからないというような、手に負えないコードになってしまうのは、神様の思し召しでしょう。そんなとき、「ポインタが不正です」とか「ゼロ除算です」といったエラーを夢想して、水蒸気にまみれてしまうのです。

コンパイラは関係なく、未定義や誤りの状態が起こりうる危険なコード断片にテストチェックがない場合、典型的なバギー・ライティングとなり、そのために不具合が現れるのです。

関数型コードチェックはコンパイラとは無関係であり、最初からそれを期待しても意味がない。

プロのプログラマーは、コンパイラのロジックを知っているので、警告を見ないことが多いのですが、コンパイラはコードの機能チェックには役に立ちません。

 
Andrei01:

変数そのものを渡して関数内で変更するのと、変数そのものはそのままで、コピーを作るのとでは、本質的な警告に大きな違いがあります。

ここでは、あくまで別の種類の警告です。名前隠しについて。

変数そのものは渡されない。それへの参照が渡される。