int main( const int argc , const char[] const argv)
有効な C++項目 #3 に「可能な限り const を使用する」と記載されているように、「これらの「定数」パラメーターを作成しない理由」を考え始めますconst
。
argc
の値がプログラムで変更されるシナリオはありますか?
この場合、履歴が要因です。C はこれらの入力を「定数ではない」と定義し、既存の C コード (のかなりの部分) との互換性が C++ の初期の目標でした。
などの一部の UNIX API はgetopt
実際に を操作するため、その理由からも argv[]
作成できません。const
(余談:getopt
のプロトタイプは、argv[]
が指す文字列を変更しないが変更する可能性があることを示唆していますが、Linux のマニュアル ページでは、 がgetopt
その引数を並べ替えていることが示されています。グループはこの順列について言及していません。)
装着const
しargc
てargv
もあまり効果がなく、次のような昔ながらのプログラミング手法が無効になります。
// print out all the arguments:
while (--argc)
std::cout << *++argv << std::endl;
私はそのようなプログラムを C で書いたことがありますが、私だけではないことを知っています。例をどこかからコピーしました。
C 標準 (ISO/IEC 9899:2011) には次のように記載されています。
5.1.2.2.1 プログラムの起動
¶1 プログラム起動時に呼び出される関数の名前は
main
. 実装は、この関数のプロトタイプを宣言していません。これは、戻り値の型が int で、パラメーターなしで定義されます。int main(void) { /* ... */ }
または 2 つのパラメーター (ここでは
argc
andと呼ばれますargv
が、宣言されている関数に対してローカルであるため、任意の名前を使用できます):int main(int argc, char *argv[]) { /* ... */ }
または同等のもの; 10)または他の実装定義の方法で。
¶2 それらが宣言されている場合、
main
関数へのパラメータは次の制約に従うものとします。
- の値は
argc
非負でなければなりません。argv[argc]
ヌルポインタでなければなりません。- の値が
argc
0 より大きい場合、 inclusiveargv[0]
からargv[argc-1]
inclusive までの配列メンバーには、プログラムの起動前にホスト環境によって実装定義の値が与えられる文字列へのポインターが含まれます。その目的は、ホスト環境の他の場所からプログラムを開始する前に決定された情報をプログラムに提供することです。ホスト環境が大文字と小文字の両方の文字を含む文字列を提供できない場合、実装は文字列が小文字で受け取られるようにする必要があります。- の値が
argc
0 より大きい場合、 が指す文字列argv[0]
はプログラム名を表します。argv[0][0]
プログラム名がホスト環境から利用できない場合、ヌル文字になります。の値がargc
1 より大きい場合、 ~ が指す文字列 はプログラム パラメータargv[1]
を表します。argv[argc-1]
- 配列が指すパラメータ
argc
およびargv
文字列はargv
、プログラムによって変更可能であり、プログラムの起動からプログラムの終了までの間、最後に格納された値を保持します。10)したがって、
int
として定義された typedef 名で置き換えることがint
できargv
ますchar **argv
。
最後の箇条書きに注意してください。と の両方が変更可能であるべきだargc
と言っています。argv
変更する必要はありませんが、変更することはできます。
argc
main()
pre-datesの関数シグネチャのため、通常は定数ではありませんconst
。
argc はスタック変数であるため、それを変更しても、独自のコマンド ライン処理以外には影響しません。
もちろん、必要に応じて自由に宣言const
できます。
仮引数の最上位const
は、関数型の一部ではありません。好きなように追加または削除できます。関数の実装で引数を使用してできることにのみ影響します。
したがって、argc
自由に追加できますconst
。
ただし、関数シグネチャを変更せずargv
に文字データを作成することはできません。const
これは、標準のmain
関数シグネチャの 1 つではなく、main
関数として認識される必要がないことを意味します。だから、良い考えではありません。
main
非おもちゃのプログラムで標準引数を使用しない正当な理由は、Windows では、国際文字を使用したファイル名などの実際のプログラム引数を表すことができないためです。これは、Windows では、Windows ANSI としてエンコードされた非常に強力な規則によるものだからです。GetCommandLine
Windows では、 API 関数に関して、より移植性の高い引数アクセス機能を実装できます。
const
要約すると、 に追加することを妨げるものは何もありませんargc
が、最も有用なconst
-ness onargv
は非標準main
関数を提供し、おそらくそのように認識されません。幸いなことに (皮肉なことに)、移植可能な深刻なコードに標準引数を使用しない十分な理由があります。main
簡単に言えば、実際には、英語のアルファベット文字のみを使用して、古い ASCII のみをサポートしています。
の署名はmain
、 からの歴史的なアーティファクトのようなものC
です。歴史的にC
はありませんでしたconst
。
const
ただし、 const の効果はコンパイル時のみであるため、パラメーターを宣言できます。
歴史的な理由は別として、argc と argv を非保持にする正当な理由const
は、コンパイラの実装が、main への引数を使用して何をしようとしているのかを認識していないためです。コンパイラの実装は、それらの引数を提供する必要があることを認識しているだけです。
const
独自の関数と関連するプロトタイプを定義する場合、作成できるパラメーターと、関数が変更する パラメーターを把握できます。
極端に言えば、すべての関数のすべてのパラメーターを宣言する必要があると宣言できconst
ます。その後、それらを変更する理由がある場合 (配列を検索するためにインデックスをデクリメントするなど)、ローカルの非const
変数を作成する必要があります。const
引数の値をそれらの変数にコピーします。これにより、忙しい仕事と余分な LOC が発生し、実際のメリットはありません。適切な静的アナライザーは、引数の値を変更していないかどうかを検出し、パラメーターを にすることをお勧めしますconst
。