ArrayIsDynamic関数の働き・役割
ArrayIsDynamic関数は、指定された配列が動的か静的かを判別するために使用されます。配列が動的である場合、関数はtrue
を返し、静的である場合はfalseを返します。
動的配列とは、プログラムの実行中にサイズを変更できる配列です。これにより、必要に応じてメモリを再割り当てし、効率的なメモリ管理が可能になります。一方、静的配列は、宣言時にサイズが固定され、実行中にそのサイズを変更することはできません。
この関数は、配列が動的かどうかを確認することで、メモリの解放や再割り当てなどの操作を適切に行うために役立ちます。
ArrayIsDynamic関数の引数について
bool ArrayIsDynamic(
const void& array[] // チェックする配列
);
ArrayIsDynamic関数は、配列が動的かどうかを確認するために、1つの引数を取ります。
この引数は、どの型の配列にも対応しており、配列が動的かどうかを調べるために必要な唯一のパラメータです。
ArrayIsDynamic関数の戻り値について
ArrayIsDynamic関数は、指定された配列が動的であればtrueを返し、静的であればfalseを返します。動的配列は実行中にサイズを変更できるのに対し、静的配列はサイズが固定されています。この関数の戻り値を活用することで、配列のメモリ管理を正しく行うことが可能です。
ArrayIsDynamic関数を使ったサンプルコード
//--- 指標の設定
#property indicator_chart_window // インジケータをチャートウィンドウに表示
#property indicator_buffers 1 // 使用するバッファ数を1に設定
#property indicator_plots 1 // プロット数を1に設定
//--- グローバル変数
double ExtDynamic[]; // 動的配列の宣言
double ExtStatic[100]; // 静的配列の宣言(サイズは100)
bool ExtFlag=true; // 処理を一度だけ行うためのフラグ
double ExtBuff[]; // 指標バッファ(データを格納するための配列)
//+------------------------------------------------------------------+
//| カスタム指標を初期化する関数 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- 動的配列にメモリを割り当て、サイズを100に設定
ArrayResize(ExtDynamic,100);
//--- 指標バッファをマッピング
SetIndexBuffer(0,ExtBuff);
//--- プロットに空の値を設定して表示しないようにする
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
//--- 正常終了を返す
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| カスタム指標の反復処理関数 |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, // 現在のバー数(レートの合計)
const int prev_calculated, // 前回の計算時に処理されたバー数
const int begin, // 計算対象の開始位置
const double &price[]) // 価格配列(未使用)
{
//--- 初回のみ処理を実行するためのフラグチェック
if(ExtFlag)
{
//--- 動的配列に対する処理
Print("+============================+");
Print("1. 動的配列のチェック:");
Print("メモリ解放前のサイズ = ", ArraySize(ExtDynamic)); // 動的配列のサイズを取得
Print("動的配列であるか = ", ArrayIsDynamic(ExtDynamic) ? "Yes" : "No"); // 動的配列かどうかをチェック
//--- 動的配列のメモリを解放
ArrayFree(ExtDynamic);
Print("メモリ解放後のサイズ = ", ArraySize(ExtDynamic)); // メモリ解放後のサイズを確認
//--- 静的配列に対する処理
Print("2. 静的配列のチェック:");
Print("メモリ解放前のサイズ = ", ArraySize(ExtStatic)); // 静的配列のサイズを取得
Print("動的配列であるか = ", ArrayIsDynamic(ExtStatic) ? "Yes" : "No"); // 静的配列が動的かどうかをチェック
//--- 静的配列のメモリ解放を試みる(実際には解放されない)
ArrayFree(ExtStatic);
Print("メモリ解放後のサイズ = ", ArraySize(ExtStatic)); // メモリ解放後のサイズを確認
//--- 指標バッファに対する処理
Print("3. 指標バッファのチェック:");
Print("メモリ解放前のサイズ = ", ArraySize(ExtBuff)); // 指標バッファのサイズを取得
Print("動的配列であるか = ", ArrayIsDynamic(ExtBuff) ? "Yes" : "No"); // 指標バッファが動的かどうかをチェック
//--- 指標バッファのメモリ解放を試みる
ArrayFree(ExtBuff);
Print("メモリ解放後のサイズ = ", ArraySize(ExtBuff)); // メモリ解放後のサイズを確認
//--- フラグを変更して再実行を防止
ExtFlag=false;
}
//--- 計算処理の最後に、次回呼び出し時のために処理済みバー数を返す
return(rates_total);
}
サンプルコード解説1:グローバル領域部分
//--- 指標の設定
#property indicator_chart_window // インジケータをチャートウィンドウに表示
#property indicator_buffers 1 // 使用するバッファ数を1に設定
#property indicator_plots 1 // プロット数を1に設定
//--- グローバル変数
double ExtDynamic[]; // 動的配列の宣言
double ExtStatic[100]; // 静的配列の宣言(サイズは100)
bool ExtFlag=true; // 処理を一度だけ行うためのフラグ
double ExtBuff[]; // 指標バッファ(データを格納するための配列)
このセクションでは、サンプルコード内のグローバル領域に定義された設定や変数について説明します。
インジケータの設定
indicator_chart_windowは、インジケータをチャートウィンドウに表示するための設定です。これは、価格チャート上にインジケータの描画結果を表示する場合に使用されます。
indicator_buffers 1は、インジケータで使用するバッファの数を指定しています。この例では、1つのバッファを使用して計算結果を保持します。
indicator_plots 1は、インジケータで表示するプロット数を指定しています。プロットとは、チャート上に描画されるデータ列を指します。
グローバル変数
ExtDynamicは、動的配列を表します。動的配列は、サイズをプログラムの実行中に変更できる配列です。この配列は、後の処理で動的にサイズを割り当てるために使用されます。
ExtStaticは、静的配列を表し、サイズが100に固定されています。静的配列は、サイズがコンパイル時に決定され、実行中に変更することはできません。
ExtFlagは、trueに初期化されているブール型のフラグです。このフラグは、サンプルコード内で一度だけ特定の処理を実行するために使われます。ExtFlagがtrueのときに配列のメモリ解放などの処理が行われ、その後falseに変更されます。
ExtBuffは、インジケータバッファとして使用される動的配列です。インジケータバッファは、インジケータの計算結果を一時的に保持するために使用されます。SetIndexBuffer関数によって、インジケータのプロットにデータがマッピングされ、チャートに描画される準備が整います。
これらのグローバル変数は、配列の動的・静的な操作やインジケータの描画に使用される重要な役割を担っています。特に、動的配列と静的配列の違いを理解することが、このサンプルコードの理解を深めるために重要です。
サンプルコード解説2:OnInit関数部分
//+------------------------------------------------------------------+
//| カスタム指標を初期化する関数 |
//+------------------------------------------------------------------+
int OnInit()
{
//--- 動的配列にメモリを割り当て、サイズを100に設定
ArrayResize(ExtDynamic,100);
//--- 指標バッファをマッピング
SetIndexBuffer(0,ExtBuff);
//--- プロットに空の値を設定して表示しないようにする
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
//--- 正常終了を返す
return(INIT_SUCCEEDED);
}
OnInit関数は、カスタムインジケータが初期化される際に最初に呼び出される関数で、インジケータの設定や初期化を行います。このセクションでは、OnInit関数内で行われる操作について説明します。
動的配列にメモリを割り当てる
ArrayResize関数を使用して、動的配列であるExtDynamicにメモリを割り当て、そのサイズを100に設定しています。動的配列は、プログラムの実行中にサイズを変更できるため、このように配列のサイズを動的に調整することができます。
指標バッファのマッピング
SetIndexBuffer関数を使って、指標バッファ(ExtBuff)をインジケータのデータにマッピングしています。これにより、インジケータが計算された結果をExtBuffに格納し、チャート上に表示することが可能になります。この操作は、指標バッファを正しく設定するために不可欠です。
プロットの設定
PlotIndexSetDouble関数を使用して、プロットに空の値を設定しています。ここでは、PLOT_EMPTY_VALUEという特別な値が設定され、これにより特定の条件でプロットを表示しないように制御しています。例えば、インジケータがデータを持たない場合や表示すべき値がない場合にこの設定が役立ちます。
正常終了を返す
最後に、return文でINIT_SUCCEEDEDを返しています。これは、OnInit関数が正常に完了したことを示し、カスタムインジケータの初期化が正しく行われたことを示します。この戻り値により、プラットフォームはインジケータの初期化が成功したかどうかを判断します。
このOnInit関数では、動的配列のメモリ管理やバッファの設定など、インジケータを正しく動作させるために必要な初期化が行われています。
サンプルコード解説3:OnCalculate関数部分その1
//+------------------------------------------------------------------+
//| カスタム指標の反復処理関数 |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, // 現在のバー数(レートの合計)
const int prev_calculated, // 前回の計算時に処理されたバー数
const int begin, // 計算対象の開始位置
const double &price[]) // 価格配列(未使用)
{
//--- 初回のみ処理を実行するためのフラグチェック
if(ExtFlag)
{
//--- 動的配列に対する処理
Print("+============================+");
Print("1. 動的配列のチェック:");
Print("メモリ解放前のサイズ = ", ArraySize(ExtDynamic)); // 動的配列のサイズを取得
Print("動的配列であるか = ", ArrayIsDynamic(ExtDynamic) ? "Yes" : "No"); // 動的配列かどうかをチェック
OnCalculate関数は、カスタムインジケータが新しいバーのデータを受け取るたびに呼び出され、必要な計算処理を実行します。この関数では、インジケータが計算対象とする価格データやその他の情報を処理しますが、このサンプルコードでは動的配列や静的配列のチェックとメモリ解放の試行を行っています。
フラグのチェック
ExtFlagがtrueである場合にのみ、特定の処理を実行します。これは、このコードの中で一度だけ実行したい処理を制御するために使用されています。初回のみメモリ解放などの処理が行われ、処理後にExtFlagはfalseに設定されます。
動的配列に対する処理
Print関数を使って、動的配列(ExtDynamic)のサイズを表示し、現在のサイズを確認しています。この時点では、動的配列に割り当てられたメモリがまだ解放されていないため、割り当てられたサイズが表示されます。
ここで使用されているArraySize関数は、指定した配列の現在のサイズ(要素数)を返します。動的配列の場合、このサイズは実行中に変わることがありますが、静的配列の場合、固定されたサイズが返されます。
次に、ArrayIsDynamic関数を使って、ExtDynamicが動的配列かどうかを確認しています。この結果もPrint関数で表示され、配列が動的であれば”Yes”、そうでなければ”No”がエキスパートログに出力されます。
三項演算子について
コード内では、三項演算子が使用されています。三項演算子は、条件式 ? 真の値 : 偽の値
という形式を持つ条件演算子です。今回のコードでは、ArrayIsDynamic関数の結果を元に、動的配列かどうかを”Yes”または”No”で出力しています。
具体的には、ArrayIsDynamicがtrueであれば”Yes”が表示され、falseであれば”No”が表示されます。三項演算子は、簡潔に条件分岐を行いたい場合に便利な書き方で、if文の代わりとしてよく使用されます。
このように、OnCalculate関数では、動的配列に対する処理がフラグによって一度だけ実行され、後でメモリ解放などの操作が行われます。
サンプルコード解説4:OnCalculate関数部分その2
//--- 動的配列のメモリを解放
ArrayFree(ExtDynamic);
Print("メモリ解放後のサイズ = ", ArraySize(ExtDynamic)); // メモリ解放後のサイズを確認
//--- 静的配列に対する処理
Print("2. 静的配列のチェック:");
Print("メモリ解放前のサイズ = ", ArraySize(ExtStatic)); // 静的配列のサイズを取得
Print("動的配列であるか = ", ArrayIsDynamic(ExtStatic) ? "Yes" : "No"); // 静的配列が動的かどうかをチェック
//--- 静的配列のメモリ解放を試みる(実際には解放されない)
ArrayFree(ExtStatic);
Print("メモリ解放後のサイズ = ", ArraySize(ExtStatic)); // メモリ解放後のサイズを確認
OnCalculate関数では、動的配列と静的配列に対して、それぞれメモリの解放や動的配列であるかのチェックを行っています。このセクションでは、その処理について解説します。
動的配列のメモリ解放
ArrayFree関数を使用して、動的配列(ExtDynamic)のメモリを解放しています。ArrayFree関数は、動的配列に割り当てられたメモリを明示的に解放するための関数です。この関数を使用することで、不要になったメモリ領域を確保しておくことなく解放でき、メモリ使用量を抑えることができます。
次に、Print関数でメモリ解放後の配列のサイズを確認しています。ArraySize関数を使うことで、配列が現在どのくらいのサイズを持っているかを調べることができます。動的配列の場合、メモリが解放されるとサイズは0になります。
静的配列に対する処理
静的配列(ExtStatic)に対しても同様に、Print関数を使用して配列のサイズを表示しています。静的配列は、宣言時にサイズが固定されているため、ArraySize関数で取得されるサイズは、常に宣言時のサイズ(この場合100)になります。
次に、ArrayIsDynamic関数を使って、静的配列が動的配列であるかどうかを確認しています。静的配列はメモリのサイズを実行中に変更できないため、ArrayIsDynamic関数はfalseを返します。Print関数で結果を表示し、動的でない場合は”No”が出力されます。
静的配列のメモリ解放
ArrayFree関数を静的配列に対して試みていますが、静的配列はメモリを動的に確保しないため、この操作は効果がありません。静的配列のメモリは、プログラムの実行が終了するまで解放されません。
このように、OnCalculate関数のこの部分では、動的配列と静的配列の違いを確認しながら、動的配列のメモリ解放や、静的配列のメモリ操作の不可性について示しています。動的配列はメモリを柔軟に管理できる一方、静的配列はコンパイル時に決まったサイズで固定されます。
サンプルコード解説5:OnCalculate関数部分その3
//--- 指標バッファに対する処理
Print("3. 指標バッファのチェック:");
Print("メモリ解放前のサイズ = ", ArraySize(ExtBuff)); // 指標バッファのサイズを取得
Print("動的配列であるか = ", ArrayIsDynamic(ExtBuff) ? "Yes" : "No"); // 指標バッファが動的かどうかをチェック
//--- 指標バッファのメモリ解放を試みる
ArrayFree(ExtBuff);
Print("メモリ解放後のサイズ = ", ArraySize(ExtBuff)); // メモリ解放後のサイズを確認
//--- フラグを変更して再実行を防止
ExtFlag=false;
}
//--- 計算処理の最後に、次回呼び出し時のために処理済みバー数を返す
return(rates_total);
}
OnCalculate関数の最後の部分では、指標バッファに対する処理が行われています。ここでは、指標バッファが動的配列であるかの確認や、メモリ解放の試みが行われています。さらに、フラグを変更することで再実行を防止しています。
指標バッファのサイズ確認
まず、Print関数を使用して指標バッファ(ExtBuff)のサイズを確認しています。ArraySize関数を使用して、現在のバッファのサイズを取得します。指標バッファは、通常動的配列として扱われるため、この段階ではメモリが確保されており、そのサイズが表示されます。
指標バッファが動的配列かどうかのチェック
次に、ArrayIsDynamic関数を使って、指標バッファが動的配列であるかどうかを確認します。指標バッファは通常動的配列として扱われるため、ArrayIsDynamic関数はtrueを返します。Print関数で結果が表示され、動的配列であれば”Yes”が、そうでなければ”No”がエキスパートログに出力されます。
指標バッファのメモリ解放の試み
次に、ArrayFree関数を使って、指標バッファのメモリ解放を試みています。動的配列である指標バッファに対しては、この関数を使ってメモリを解放することが可能です。メモリ解放後に、再度ArraySize関数を使用してサイズを確認します。動的配列の場合、メモリ解放後のサイズは0になります。
フラグの変更
ExtFlagがtrueの間、この一連の処理が実行されますが、処理が完了した後、ExtFlagをfalseに変更しています。これにより、この処理は次回のOnCalculate関数呼び出し時には再実行されず、一度のみ実行されるようになります。このフラグによる制御は、特定の初回処理を一度だけ実行したい場合に有効です。
戻り値を返す
最後に、OnCalculate関数はrates_totalを返しています。rates_totalは現在のバー数を示しており、これによりプラットフォームは次回呼び出し時に処理がどこまで行われたかを判断できます。この戻り値により、未処理のバーに対してのみ処理を行うことができます。
この部分では、指標バッファに対するメモリ解放やサイズ確認の操作が行われており、動的配列である指標バッファの扱い方や、効率的なメモリ管理の方法が示されています。また、処理の再実行を防止するためのフラグ管理も重要なポイントです。