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