エラー、バグ、質問 - ページ 2045

 

しかし、そこで間違った配列次元を 設定してしまったので、もしかしたら何らかの影響を受けてしまったのかもしれません(全く影響しないはずなのですが)。

dimension = 3 で試してみてください。

template<typename T>
int F1(const T& array[]) { return ArrayMaximum(array); }

template<typename T>
int F2(const T& array[]) { return F1(array); }

void OnStart()
  {
    int arr[3]= { 1, 2, 3 };
    Print(F2(arr));  // Выдаёт -1 !!!
  }
 

不一致の原因を発見。OPTIMIZE=0ではエラーになりますが、OPTIMIZE=1ではエラーになりません。普段はOPTIMIZE=0しか使っていません。

 
fxsaber:

その結果に対して論理的な(矛盾しない)説明が見つかれば、バグはないと思うのです。C++と結果が一致しないのにバグを証明することは許されないと思うのです。誰かがそう思ってやったことがC++にあるんです。でも、そう思っていなかったから、やらなかったのかもしれない。だから、外にあるものを参考にするのではなく、自分の中の「こうでなければならない」という概念に頼ったほうがいいんです。そして、この「自分のもの」が、本当に自分のものであることが望ましいのです。プログラミングの経験を積んでいくうちに、「こうあるべき」という固定観念が気づかないうちに押しつけられた結果ではなく、「こうあるべき」と思うようになったのです。

自分なりの説明がない場合は、誤りがないということです。そして、もし1年後にこの説明が現れて、むしろ納得のいくものであった場合、誰もがすべてをやり直さなければならないのでしょうか?C++では、なぜこうするのか、ああしないのか、すでに100回は考えているはずです。また、MQLとC++で何か設定が違っていて、その逆ではない場合に説明が必要です。

 
Alexey Viktorov:
静的変数は、任意の式で初期化できる単純なローカル変数とは異なり、その型に対応する定数または定数式で 初期化することができる。


でも、機能ではありません。

静的なクラスインスタンスは禁止されるべきです。

 

そして、変数の初期化については、こちらが詳しいです。ドキュメントに記載されていることに従えば、他のグローバル/静的変数も参照できないことになります。一定の表現ではないため。

int a= 1;
int b= a+1;  // Согласно документации, такая инициализация не возможна

void OnStart()
{
  Print(b);
}

しかし、今のところうまくいっています。そして、多くの人が気づかないうちに、いつもそのような構成を使っていたのでしょう。しかし、開発者がいつそれを無効化してもおかしくないことが判明しました。また、関数の初期化の場合と同様に、これらのコードはコンパイルには成功しますが、正しく動作しません。全てにおいて、MQLは時限爆弾なのです。

 
Alexey Navoykov:

そして、もうひとつ、変数の初期化に関する ことです。ドキュメントに記載されていることに従えば、他のグローバル/静的変数も参照できないことになります。一定の表現ができないからです。

//+------------------------------------------------------------------+
//|                                                   ExpertMACD.mq5 |
//|                   Copyright 2009-2017, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
CExpert ExtExpert;

はコンストラクタ関数で初期化されます - 禁止!

これは、前回の書き込みを論理的にまとめると

アレクセイ・ナヴォイコフ

矛盾の原因が判明。OPTIMIZE=0ではエラーになるが、OPTIMIZE=1ではエラーにならない。普段はOPTIMIZE=0しか使っていません。

32ビット端末では、OPTIMIZEでエラーが発生します。

int g1( int& t[] ) { return ArraySize( t ); }
int g2( int& t[] ) { return g1( t ); }
void OnStart()
{
        int t[] = { 1, 2, 3, 4, 5 }; //всего 5
        Print( g2(t)); //Результат:          3
}
 
A100:

はコンストラクタ関数で初期化されます - 禁止!

これは、前回の書き込みを論理的にまとめると

まあ、そこはその人が間違った表現をしているだけなんですけどね。もちろん、初期化関数の話ではなく、初期化値の話です。


そして、なんといっても禁止事項。自分からトラブルを起こすことはないのです。しかし、この禁止事項がコンパイラによって一切制御されず、言語ルールを回避するアルゴリズムを生成する場合、全く適合しない。これからは、そんなことを探すためにすべてのコードを掘り起こし、常に警戒しなければならなくなります。まあ、そんなプログラミングはクソだ、旧ビルドのままがいい。

 
Alexey Navoykov:
なるほど、それなら謝ります、すぐには気づきませんでした。もちろん、よくもまあ、誰にも言わずにひっそりと変更できたものだと驚いています。理解できないのは、なぜコンパイラは無効な演算が実行されたことに反応しないのか、ということです。つまり、どのような場合でもバグは存在するのです。
なぜ、無効だと思うのですか?ご自身の判断でご利用ください。全体の問題としては、関数によって静的変数が初期化さ れると、初期化が「一時停止」され、関数が実行されることです。そして、上記の例では、その関数の中にまだ初期化されていない静的変数があります。したがって、関数で初期化された変数は、別の値をとります。
 
Alexey Navoykov:

そして、変数の初期化については、こちらが詳しいです。ドキュメントに記載されていることに従えば、他のグローバル/静的変数も参照できないことになります。一定の表現ではないため。

しかし、今のところうまくいっています。そして、多くの人が気づかないうちに、いつもそのような構成を使っていたのでしょう。しかし、開発者がいつそれを無効化してもおかしくないことが判明しました。また、関数の初期化の場合と同様に、これらのコードもコンパイルは成功しますが、正しく動作しません。全体として、MQLのコード全体がスローモーションで動く地雷のようなものなのです。

まあ...この例では、ドキュメントの記述と齟齬はないのですが......。ドキュメントからの引用をよく見てください。

静的変数は、任意の式で初期化できる単純なローカル変数とは異なり、その型に適した定数または定数のような式で 初期化することができます。


または定数式で

int a= 1;
int b= a+1;

この初期化が可能です。なぜなら、変数 'a' は定数で初期化され、変数 'b' は定数式で初期化されるからです。

 
A100:

その場合、クラスの静的インスタンスを禁止する必要があります - クラスはコンストラクタ関数で初期化されるからです。

に注目する。

トレーディング、自動売買システム、トレーディング戦略のテストに関するフォーラム

バグ、バグ、質問

アレクセイ・ビクトロフ さん 2017.10.18 09:19

なぜ変わったと思うのか、なぜ受け入れられないのか。ご自身の判断でご利用ください。全体の問題は、静的変数が 関数によって初期化さ れると、初期化が「一時停止」され、その関数が実行されることです。そして、上記の例では、その関数の中にまだ初期化されていない静的変数が あります。したがって、関数で初期化された変数は、別の値をとります。
残念ながら、コンストラクタでスタティック変数を宣言して初期化することが可能かどうかは分かりませんが、教えていただければと思います。そして、やはり初期化シーケンスが非常に重要なのですね。