9

可能な限り値パラメーターを宣言するのが好きですがconst、SOを検索することで、それはそれほど珍しいことではないことがわかりました。このような:

int add(const int a, const int b)
{
    ...
}

しかし、私は疑問に思っていconstます。は、関数のインターフェースの一部ではなく、関数の実装の詳細です。したがって、それをプロトタイプに入れる必要はないようです。

上記の関数のこのプロトタイプは問題なく機能しているようです。

int add(int a, int b);

それでも、たとえば、メイン関数のargcをconstとして宣言すると、問題が発生する可能性があるという問題について聞いたことがあります。

int main(const int argc, const char* const argv[])

それで、それはそれを意味し、結局のところ同一ではありませんかint add(int a, int b)int add(const int a, const int b)

そして、それが技術的に問題がない場合、それは私がすべきことですか?プロトタイプで変数名を除外することもできますが、除外しないので、どちらも除外するべきではないでしょうconstか。

4

3 に答える 3

10

関数型が異なっていても問題ありませんが、関数型の一部であるものとそうでないものを知る必要があります。あなたの場合、constパラメータのforは重要ではないので、関数の型は同じですが、宣言は定義とは異なるように見えます。

あなたの場合それは

8.3.5関数[dcl.fct]

5単一の名前は、単一のスコープ内の複数の異なる機能に使用できます。これは関数のオーバーロードです(13節)。関数のすべての宣言は、戻り型とパラメータ型リストの両方で正確に一致する必要があります。関数のタイプは、次のルールを使用して決定されます。各パラメーターのタイプ(関数パラメーターパックを含む)は、独自のdecl-specifier-seqおよびdeclaratorから決定されます。各パラメータのタイプを決定した後、「Tの配列」または「Tを返す関数」タイプのパラメータは、それぞれ「Tへのポインタ」または「Tを返す関数へのポインタ」に調整されます。パラメーター型のリストを作成した後、パラメーター型を変更する最上位のcv修飾子は、関数型を形成するときに削除されます。結果として得られる変換されたパラメータータイプのリスト、および省略記号または関数パラメーターパックの有無は、関数のパラメータータイプリストです。[注:この変換は、パラメーターのタイプには影響しません。例えば、int(*)(const int p, decltype(p)*)int(*)(int, const int*)は同じタイプです。—エンドノート]

どうやら説明が必要なので、ここで説明します。この場合の重要な文は次のとおりです。パラメーター型のリストを作成した後、パラメーター型を変更する最上位のcv修飾子は、関数型を形成するときに削除されます。

これは、すべての最上位のcv修飾子が削除されることを意味します。トップレベルの意味を説明するために、aが何をconst指しているかを強調するために、違法な方法で型を記述します。

  • const int= (const (int))->これはトップレベルですconst
  • const int*= ((const (int))*)->トップレベルではなく、2番目のレベルにあります
  • const int* const= (((const (int))*) const)->2番目constはトップレベルです
  • const int&= ((const (int))&)->トップレベルではありません

これにより、関数の型に関する誤解が解消されることを願っています。

他の質問については、宣言と定義を同一にしておくことをお勧めします。これは、人々を混乱させる可能性があるためです(この質問で証明されているように;)。

あなたが与えたその例のためにmain

int main( const int argc, const char* const argv[] )

は、上記の標準からの引用によれば、次のようになります。

int main( int argc, const char* const* argv )

したがって、追加されconstたforは、削除さargvれるトップレベルconstにはなりません。したがって、これは、の形式が正しくない関数型でmainあり、次のことを期待しています。

int main( int argc, char** argv )

パラメータ名を省略することについての最後の質問:私にとって、それらは関数のドキュメントの一部であるため、私はそれをしません。それらは、関数の意図とセマンティクスを伝達します(賢明に選択した場合)。

于 2013-03-08T15:39:10.040 に答える
1

const関数の宣言と定義の間で関数パラメーターのトップレベルが異なっていても問題ありませんが、すべてのコンパイラーにバグがないわけではないことに注意してください。たとえば、Oracle Sunコンパイラには、さまざまな問題が発生するという長年の問題int f(int)ありint f(const int)ます。

参照によって実際に渡すことを意図した混乱の可能性を回避するために、通常、パブリック関数宣言でconstトップレベルを回避することをお勧めします。また、コンパイラの問題の可能性を回避するために、関数定義でも回避することをお勧めします。const

char **(引数リストでに変更しconst char* const argv[]ても、最上位のconstは追加されないことに注意してください。これは、本物の署名の変更です。関数パラメーターリストでの変更char**と同等です。)char** const

于 2013-03-08T17:00:57.987 に答える
0

const for valuesは私の関数の実装の詳細であり、そのインターフェースの一部ではありません。

それはあなたの考えの欠陥です。参照とポインターについて話すとき const、インターフェースと関係があるとき、それはあなたが渡すものが関数によって変更されないことをインターフェースを使用するプログラマーに伝えます。これはコンパイラーに同じことを伝え、プログラマーをこのコントラクトにバインドします。

引数のある関数とconst引数のない関数constは異なります。

ただし、値を渡すと引数がコピーされます。その場合、引数を変更しても問題はありません。 あなたintのsは値によって渡されますが、これconstはあまり違いはありません。

しかし、個人的には、それが一貫性のないインターフェイスを持つことを悪用し、インターフェイスを場所ごとに異なるものにする理由ではないと思います。

refを渡すのに対し、reftoはreftonon-とconstはまったく異なりconstます。

于 2013-03-08T15:39:17.850 に答える