mql5言語の特徴、微妙なニュアンスとテクニック - ページ 151

 
fxsaber:

静的変数は、最初の呼び出しで初期化されます。

開発者がなぜこのようなことをしたのか、推測するのは困難です。私は、コンパイル時に未知の値で定数変数を初期化する、というバグだと考えています。

普段から、何をいつ初期化すればいいのか、そうやって確認しています

//+------------------------------------------------------------------+
void OnStart()
{
   f(333);
   f(2);
}
//+------------------------------------------------------------------+
int init_static()
{
   Print(__FUNCTION__);
   return(1);
}

void f( const int i )
{
  static const int j = init_static();
  
  Print(__FUNCTION__," , j =",j);
}

2019.11.30 11:09:32.456 tst (EURUSD,H1) init_static

2019.11.30 11:09:32.457 tst (EURUSD,H1) f , j =1

2019.11.30 11:09:32.457 tst (EURUSD,H1) f , j =1


この例では、すべてが正しく初期化され、コンパイラは定数jにそれ以上の値を代入することを許可していません - コンパイルエラーが発生します。

 
Vladimir Simakov:

問題なのは、どう考えても概念的な間違いなので、使う意味がないことです。

まあ、いずれにせよ概念的な間違いなので、使う価値はないのですが。

 
Alexey Navoykov:

まあ、いずれにしても概念的な間違いなので、使わない方がいいでしょう。

しかし、なぜコンセプチュアルなのか。逆に、コンパイル時にどのような値でスタティック変数を初期化すればよいのかわからない場合、最初の呼び出しで初期化することが有効です。

 
Alexey Navoykov:

まあ、とにかく概念的な間違いだから使うなよ。

MVS C++17の実装。

静的ローカル変数

ブロックスコープで static またはthread_local 指定の下に宣言された変数 (C++11 以降)は、staticまたは thread (C++11以降)の 保存期間を持ちますが、制御がその宣言を最初に通過したときに初期化されます(初期化がゼロ または定数初期化 でない限り、ブロックに最初に入る前に実行することができます)。それ以降の呼び出しでは、この宣言はスキップされる。

初期化で例外が発生した 場合、その変数は初期化されたとはみなされず、次に制御が宣言を通過する際に再度初期化が試みられる。

初期化が再帰的にその変数が初期化されているブロックに入る場合、動作は不定です。

複数のスレッドが同時に同じ静的ローカル変数を初期化しようとした場合、初期化は正確に一度だけ行われます(std::call_onceによる 任意の関数でも同様の動作を得ることができます)。

注:この機能の通常の実装では、ダブルチェックロックパターンの変種を使用し、すでに初期化されたローカル静的情報の実行時オーバーヘッドを単一の非原子のブール値比較に低減しています。

(C++11以降)

ブロックスコープのスタティック変数のデストラクタは、プログラム終了時に呼び出さ れますが、初期化が正常に行われた場合にのみ呼び出されます。

同じインライン関数(暗黙的にインライン化されている場合もある)のすべての定義にある関数ローカル静的オブジェクトは、すべて1つの翻訳ユニットで定義された同じオブジェクトを参照しています。

個人的には、そのような実装がmqlで合法であれば、docsに明記する必要があるだけで、大賛成です。

 
Vladimir Simakov:

では、なぜコンセプチュアルなのか。逆に、コンパイル時にスタティック変数をどのような値で初期化すればよいかわからないこともあり、そのようなときに役立つのがファーストコールによる初期化です。

そこで、ゼロ(デフォルト)値で初期化する必要があります。 また、なぜ最初に出会った値で初期化するのでしょうか? そうすると、この関数の動作は、この関数の呼び出し順序によって決まり、副作用が発生します。しかも不正解です。外部から内部を初期化したい場合は、関数ではなくクラスを使用したほうがよいでしょう。

しかし、実は「コンパイルできない」というのは間違いで、C++では、不思議なことに、そんなことは思いもよらなかったが、動作する。

 
Alexey Navoykov: C++では、不思議なことに、そのようなことは思いもよらなかったのですが、動作します。

概念的な問題はなく、問題なのはそうでない場合です。

void fn() {
   static int i = fn_from_other_cpp();
}

そして、破壊の順序は厳密には逆である。

 
Vict:

これは常にそうであり、概念的な問題はない。そうでなければ問題がある。

あなたの例は少し違いますね。
 
Slava:

コンテキストメニューの「編集」を選択した後、ナビゲータがex5と同じパスにあるオリジナルのmq5を見つけることができない。

ex5がShared Projectsからscriptsフォルダに移動し、mq5が存在するため

修正します。テスター 設定と同じスマート検索をしよう

また、逆の状況もあります。Favorites Navigatorで、ex5がない場合(コンパイルエラーがあったなど)、mq5-editingに行くことができない(mq5は使える)。これも直してください。

 
fxsaber:

また、逆の状況もあります。Favorites Navigatorで、ex5がない場合(コンパイルエラーがあったなど)、mq5-editingに切り替えることができない(mq5は使用可能)。これも直してください。

2250で結構です。

急がれています。2251 - mq5 が開きません。

 
fxsaber:

2250で結構です。

急げよ。2251 - mq5 が開きません。

あるのでしょうか?持っていますか?どのような経路をたどっているのでしょうか?

どうすれば再現できるのか?

理由: