C++ プログラムの終了
C++ では、次の方法でプログラムを終了できます:
exit
関数
<stdlib.h> で宣言された exit
関数は、C++ プログラムを終了します。 exit
の引数として指定された値は、プログラムのリターン コードまたは終了コードとしてオペレーティング システムに返されます。 慣例により、ゼロのリターン コードは、プログラムが正常に完了したことを意味します。 <stdlib.h> で定義された定数 EXIT_FAILURE
と EXIT_SUCCESS
を使用して、プログラムの成功または失敗を示すことができます。
abort
関数
標準インクルード ファイルの <stdlib.h> で宣言された abort
関数も、C++ プログラムを終了します。 違いexit
abort
は、exit
C++ ランタイム終了処理を実行できる点です (グローバル オブジェクトデストラクターが呼び出されます)。 abort
はプログラムを直ちに終了します。 abort
関数では、初期化されたグローバルな静的オブジェクトの通常のデストラクション処理は実行されません。 また、atexit
関数を使用して指定されている特殊な処理も実行されません。
Microsoft 固有: Windows の互換性上の理由から、Microsoft の実装では、特定の abort
状況で DLL 終了コードを実行できる場合があります。 詳細については、abort
を参照してください。
atexit
関数
プログラムが終了する前に実行されるアクションを指定するには、atexit
関数を使用します。 atexit
の呼び出し以前に初期化されたグローバル静的オブジェクトは、終了処理関数の実行前に破棄されません。
main
の return
ステートメント
return
ステートメントを使用すると、main
から戻り値を指定できます。 最初のステートメントはreturn
、他return
のmain
ステートメントと同様に機能します。 自動変数はすべて破棄されます。 次に、 main
戻り exit
値をパラメーターとして呼び出します。 次の例を考えてみましょう。
// return_statement.cpp
#include <stdlib.h>
struct S
{
int value;
};
int main()
{
S s{ 3 };
exit( 3 );
// or
return 3;
}
exit
前の例の and return
ステートメントも同様の動作をしています。 どちらもプログラムを終了し、値 3 をオペレーティング システムに返します。 違いは、exit
ステートメントでは自動変数s
return
を破棄しないということです。
ただし、C++ では、void
以外の戻り値の型を持つ関数は、値を返す必要があります。 main
関数は例外であり、return
ステートメントなしで終了できます。 その場合は、呼び出しプロセスに実装固有の値を返します。 (既定では、MSVC は 0 を返します)。
スレッドオブジェクトと静的オブジェクトの破棄
直接呼び出す場合 (またはステートメントのmain
後return
に呼び出exit
された場合) は、現在のスレッドに関連付けられているスレッド オブジェクトが破棄されます。 次に、静的オブジェクトは初期化の逆の順序で破棄されます (関数の呼び出しが指定されている atexit
場合は、その呼び出しの後)。 次の例は、こうした初期化やクリーンアップがどのように機能するのかを示します。
例
以下の例では、静的オブジェクト sd1
と sd2
は、main
に入る前に作成、初期化されます。 このプログラムが return
ステートメントを使用して終了した後、最初に sd2
が破棄され、その後に sd1
が破棄されます。 ShowData
クラスのデストラクターは、これらの静的オブジェクトに関連付けられたファイルを閉じます
// using_exit_or_return1.cpp
#include <stdio.h>
class ShowData {
public:
// Constructor opens a file.
ShowData( const char *szDev ) {
errno_t err;
err = fopen_s(&OutputDev, szDev, "w" );
}
// Destructor closes the file.
~ShowData() { fclose( OutputDev ); }
// Disp function shows a string on the output device.
void Disp( char *szData ) {
fputs( szData, OutputDev );
}
private:
FILE *OutputDev;
};
// Define a static object of type ShowData. The output device
// selected is "CON" -- the standard output device.
ShowData sd1 = "CON";
// Define another static object of type ShowData. The output
// is directed to a file called "HELLO.DAT"
ShowData sd2 = "hello.dat";
int main() {
sd1.Disp( "hello to default device\n" );
sd2.Disp( "hello to file hello.dat\n" );
}
このコードを記述するもう 1 つの方法は、ブロック スコープを ShowData
持つオブジェクトを宣言することです。これにより、スコープ外になったときに暗黙的に破棄されます。
int main() {
ShowData sd1( "CON" ), sd2( "hello.dat" );
sd1.Disp( "hello to default device\n" );
sd2.Disp( "hello to file hello.dat\n" );
}
関連項目
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示