33

関数の宣言とその定義が値パラメーターについて合意する必要がないと述べられている場合、定数の正当性についての質問はほとんどないことを私は知っています。これは、値パラメーターの定数が関数内でのみ重要であるためです。これは問題ありません:

// header
int func(int i);

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

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

「実際、コンパイラーにとって、値パラメーターの前にこのconstを含めるかどうかに関係なく、関数のシグニチャーは同じです。」

「関数宣言でconstの値渡しパラメーターを使用しないでください。変更しない場合は、同じ関数の定義でパラメーターconstを作成してください。」

2番目の段落は、宣言にconstを含めないことを示しています。これは、値パラメーターの定数がインターフェース定義の一部として無意味であるためだと思います。実装の詳細です。

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

// 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をヘッダーファイルから除外するという極端なことをしますか?ポインタ値を設定することも同様に役立ちますか?なぜまたはなぜそうではないのですか?

いくつかの参考文献:

C ++ constキーワード-自由に使用しますか? 関数パラメーターに「const」を使用する

constvalueパラメーターが役立つ場合の例:

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
}
4

6 に答える 6

14

関数constで値パラメーターを作成することは不要であるため、行うのは悪いことであることを何度も読みました。

ただし、(質問の最後の例のように)私の実装が意図しないことを行わないことを確認するのに役立つことがあります。

したがって、呼び出し元に価値を追加しない場合もありますが、実装者としての私に少しの価値を追加することがあり、呼び出し元から何も奪うことはありません。だから私はそれを使っても害はないと思います。

たとえば、バッファへの2つのポインタ(開始へのポインタと終了へのポインタ)を受け取るC関数を実装している場合があります。データをバッファに入れますが、最後をオーバーランしないようにします。したがって、関数内には、データを追加するときにポインターをインクリメントするコードがあります。バッファーの終わりへのポインターをconstパラメーターにすると、実際にインクリメントする必要のあるポインターではなく、誤って終了境界ポインターをインクリメントするバグをコード化しないようになります。

したがって、次のようなシグネチャを持つfillArray関数は次のようになります。

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

pEnd私が本当にインクリメントするつもりであるときに、誤ってインクリメントするのを防ぎますpStart。それは大きなことではありませんが、Cで一定期間プログラミングしたすべての人がそのようなバグに遭遇したことは間違いありません。

于 2009-11-12T17:54:53.603 に答える
13

私の見解:

それは悪い考えではありませんが、問題は軽微であり、あなたのエネルギーは他のものによりよく使われるかもしれません。

あなたの質問では、エラーが発生する可能性のある良い例を示しましたが、場合によっては次のようなことをすることもあります。

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

   /* … */
}

長所と短所はどちらにしてもマイナーです。

于 2009-11-12T17:58:16.277 に答える
1

残念ながら、一部のコンパイラ(Sun CC!)は、constで宣言された引数とそうで宣言されていない引数を誤って区別し、未定義の関数に関するエラーが発生する可能性があります。

于 2009-11-12T18:00:20.470 に答える
0

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

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

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

これは、一部の人々がパブリック仮想メソッドを持たないことを推奨する理由に似ています(関数virtual-nessは、クライアントから隠されるべき実装の詳細です)が、私はその特定の陣営にはいません。

于 2009-11-12T18:50:12.770 に答える
0

constキーワードが存在する場合。'i'(constタイプ)の値は変更できないことを意味します。'i'の値がfoo関数内で変更された場合、コンパイラはエラーをスローします: "

constオブジェクトを変更できません

ただし、「* i」を変更すると(つまり、* i = 3;)、「i」の値ではなく、「i」が指すアドレスの値を変更することになります。

実際、const関数は、関数によって変更されるべきではない大きなオブジェクトに適しています。

于 2016-04-12T14:39:04.867 に答える
-2

私はこのような状況でのconstの正当性が好きです:
void foo(const Bar &b) //I know b cannot be changed
{
//do something with b
}

これによりb、変更を恐れずに使用できますが、コピーコンストラクターのコストを支払う必要はありません。

于 2009-11-12T18:02:25.660 に答える