2009-11-12 11 views
24

関数の宣言とその定義が値のパラメータについて合意する必要がないと述べられているconstの正確さについては、ほとんど疑問がありません。これは、値パラメータのconstanceが関数内でのみ重要であるためです。これは問題ありません:値の精度のconst

// header 
int func(int i); 

// cpp 
int func(const int i) { 
    return i; 
} 

本当にこれはベストプラクティスですか?誰もそれを見たことがないから。私は、これは議論されている他の場所で(ソースのわからない)この引用を見てきました:

"In fact, to the compiler, the function signature is the same whether you include this const in front of a value parameter or not."

"Avoid const pass-by-value parameters in function declarations. Still make the parameter const in the same function's definition if it won't be modified."

第二段落は宣言でのconstを入れないように言います。これは、値パラメータのconstanceがインターフェイス定義の一部として無意味であるためと考えられます。実装の詳細です。

この推奨事項に基づいて、ポインタパラメータのポインタ値にも推奨されていますか? (あなたが参照を再割り当てすることはできませんので、それは、参照パラメータの意味がありません。)

// header 
int func1(int* i); 
int func2(int* i); 

// cpp 
int func1(int* i) { 
    int x = 0; 

    *i = 3; // compiles without error 
    i = &x; // compiles without error 

    return *i; 
} 
int func2(int* const i) { 
    int x = 0; 

    *i = 3; // compiles without error 
    i = &x; // compile error 

    return *i; 
} 

概要:値パラメータを作成すると、いくつかの論理エラーをキャッチするのに便利です。それはベストプラクティスですか?ヘッダーファイルからconstを抜け出すのは極端ですか?ポインタの値をconstするのと同じくらい便利ですか?なぜ、なぜそうではないのですか?

いくつかの参照:

C++ const keyword - use liberally? Use of 'const' for function parameters

constの値のパラメータが有用でたときの例:

bool are_ints_equal(const int i, const int j) { 
    if (i = j) { // without the consts this would compile without error 
     return true; 
    } else { 
     return false; 
    } 
    // return i = j; // I know it can be shortened 
} 
+0

それは、この場合の「もし(I = J)」エラーをキャッチしますが、そのようなすべてのエラーをキャッチしていません私はその特定の根拠についてあまり興奮しません(変数で同じエラーを出すことができるので)。 constを指定しなくても、コンパイラは警告を出さなければならないと警告する必要があります。 – nobar

+0

'if(i = j)'で興奮している点は、const値のパラメータが単なる毛羽立ちではないことを認識することです。 Michael Burrの例はこれよりも優れています。 – jmucchiello

+2

関数のパラメータを変更していない状況では、A)安全です。B)自己文書化しています。また、プロトタイプとヘッダーにはconstとマークする必要があります。関数ヘッダーでのみ実行すると混乱します。関数内に一時変数を作成する議論は、おそらくパラメータconstを宣言する必要がない状況です。それは私の2ペニーです。 –

答えて

7

私のテイク:

それは悪い考えではないですが、問題は軽微であり、あなたのエネルギーは、より良い他のものに費やされる可能性があります。あなたの質問に

は、あなたはそれがエラーをキャッチする可能性がある場合の良い例を提供するが、時折、あなたはまた、このような何かをやって終わる:

void foo(const int count ...) 
{ 
    int temp = count; // can't modify count, so we need a copy of it 
    ++temp; 

    /* ... */ 
} 

長所と短所がいずれかの方法軽微です。

+3

+1は悪い考えではないと言っています。しかし、あなたがパラメータを内部にコピーする前に、私は単にconstを削除します(おそらく、あなたがパラメータを操作しないという原則として "カウント"を常にコピーする場合を除いて)。 –

+8

通常、意味の意味を変えているような変数を変更します。たとえば、void foo(const int index0based){const int index1based = index0based + 1;}これをインデックスと呼んで変更することができますが、これは5年後の不良メンテナンスプログラマーにとってははるかに明確です。 – Bill

+0

@Bill、抜群のポイント! –

9

私は、関数の値パラメータを作ることを何度も読みましたconstは不要なので、やり方が悪いです。

しかし、私の実装が私の意図していないことをしていないかどうかのチェックとして役立つことがあります(質問の最後の例のように)。

したがって、呼び出し元に値を追加しないかもしれませんが、実装者として私に小さな値を追加することがあり、呼び出し元から何も離れません。だから私はそれを使用して害を参照してください。

たとえば、私はバッファへの2つのポインタ、つまり開始点へのポインタと終了点へのポインタをとるC関数を実装しているかもしれません。私はバッファにデータを置くつもりだが、私が最後をオーバーランさせないようにしたい。関数の内部には、データを追加する際にポインタをインクリメントするコードがあります。バッファの末尾にポインタを設定すると、実際にインクリメントしなければならないポインタの代わりに、誤って終了境界ポインタをインクリメントするバグをコード化しないようになります。

したがって、このようなシグネチャを持つfillArray機能:

size_t fillArray(data_t* pStart, data_t* const pEnd); 

は、私は本当にpStartをインクリメントすることを意味したときに誤ってpEndをインクリメントするから私を防ぐことができます。それは巨大なことではありませんが、私はC言語でいつでもプログラムしている人は、このようなバグを乗り越えていると確信しています。その上

+0

優れています。私はconstポインタ値の良い例を探していました。 – jmucchiello

1

残念ながら、いくつかのコンパイラは、(私は日CC、あなたの探しています!)が誤ってのconstと宣言されていないもののように宣言された引数を区別し、そしてあなたは、未定義の機能に関するエラーを得ることができます。

-2

は、私はこのような状況のためのconstの正しさが好き:
void foo(const Bar &b) //I know b cannot be changed
{
//do something with b
}

これは私がそれを修正することを恐れずbを使用することができますが、私はコピーコンストラクタの費用を支払う必要はありません。

+8

参照パラメータについては言及していません。値パラメータのみ。 – jmucchiello

0

私は、これはあなたの個人的なスタイルに依存していると思います。

これは、追加したり、クライアントがあなたの関数に渡すことができるものに減算されません。本質的には、コンパイル時のアサーションのようなものです。価値が変わらないことを知ることができれば、それを進めてください。しかし、私は他人がそれをする大きな理由は見ません。私はそれをしないかもしれ

一つの理由は、valueパラメータのconstのネスは、クライアントが知っている必要はありませんことを、実装の詳細であるということです。あとで(意図的に)関数を変更してその値を実際に変更する場合は、関数のシグネチャを変更する必要があります。これにより、クライアントの再コンパイルが強制されます。

これは一部の人は何のパブリック仮想メソッド(仮想ネスは、クライアントから隠されるべき実装の詳細である機能)を有していないお勧めする理由に似ていますが、私はその特定のキャンプではありませんよ。

+2

質問を読んでください。ヘッダファイルにはconstがありません。なぜなら、呼び出し側は、実装がローカル変数を変更するかどうかを気にしないからです。これは、実装側でそれが価値があるかどうかについての厳密な質問です。 – jmucchiello

0

constキーワードの存在がある場合。 'i'(const型)の値は変更できません。 「私は」fooの機能コンパイラ内部で変更された値がエラーをスローする場合:「

Can not modify const object

をしかし、 『* I』(すなわち* I = 3;)を変更すると、 『I』の値を変更していないことが、実際には、constの関数は関数によって変更すべきではありませんラージオブジェクトに対して適切である「I」

で指摘した。

0

のアドレスの値我々は、すべての時間からの時間に他の誰かのC++コードを解く必要があります。そして、それ他の誰かのC++コードは、定義上完全な混乱です:D

コンパイラが文句を言うまで、私は常にそれを解読するために(ローカルの&グローバルデータフロー)、すべての変数定義にconstを入れます。これはまた、値の引数をconst修飾することを意味し、実際に私に気づかないうちに関数の中間で変更された変数を避けるのに役立ちます...

他の誰かが、どこにでも(値パラメータを含む)のconstを持っているときに、私は本当に感謝:D