C / C ++では、可能であればパラメーターとローカル変数で 'const'を使用する必要がありますか?


13

この質問は、Java に関する質問にfinal触発されたものです。

C / C ++では、const可能な限り使用する必要がありますか?

パラメータでの使用constに関して、関連する質問が既にあることは知っています。残念ながら、その質問とその回答は関数のパラメーターに関するものだけなので、私の質問には完全には答えませんが、他のケース(たとえば、ローカル変数)についても知りたいです。

また、その質問に対するほとんどすべての回答constは、変数のアクセス可能性に関する有用な情報が含まれているため、使用する必要があると述べています。しかし、これはJavafinalを使用することに関する回答と矛盾するようです。このfinal情報は、余分な情報が含まれていない場合は不必要であり、コードを短く簡潔にするために省略する必要があると述べています。

それで、const可能な限り使用すべきですか?もしそうなら、なぜconstC ++でのアドバイスfinalがJavaでのアドバイスと異なるのですか?

回答:


18

まず第一に、Javaを参照したのでfinal、それはとはまったく異なる獣ですconst。最後は参照が変更できないことを意味しますが、可変性については何も述べていません。Constはさらに、「const参照は変更できない」と言っており、これははるかに強力な保証です。Javaでこれを行うには、内部状態が最終であり、構築時に決定される必要があります。Constははるかに使いやすく、既存のオブジェクトをconst参照に「昇格」できます。

はい、できる限りconstを使用してください。それはあなたのコードが何かを変えないという契約をします。constパラメータを受け付ける関数に非const変数を渡すことができることを覚えておいてください。いつでもconstを追加できますが、削除することはできません(constキャストがなければ、これは非常に悪い考えです)。

const-correctnessは時々退屈かもしれませんが、それは不変性を保証するのに役立ちます。これは、スレッドがオブジェクトを共有するマルチスレッドコードでは重要です。特定のタスクをより効率的にします。状態をコピーする代わりに、同じ不変オブジェクトを再利用するだけです。ライブラリは、プログラマにライブラリの根本であるブラックホールで予期しない方法でオブジェクトが変更されないことを保証するために、constパラメータを受け入れる場合があります。


1
投票まであなたはそれを説明しているためfinalconst同じ保証を持っていません。
Bill Door

2
Constnessは、可変性ではなく、書き込み可能性についてです。
バシレフ2016年

@Basilevsオブジェクトに書き込むとどうなりますか?変異します。オブジェクトをどのように変更しますか?それに書いてください。

4
const参照に書き込むとどうなりますか?コンパイル時エラー。別の非const参照を介してconst参照によってどこかで参照されているオブジェクトに書き込むとどうなりますか?変異します。不変オブジェクトは変更できないため、const参照は必ずしも不変オブジェクトを参照するわけではありません。
バシレフ2016年

@Basilevs観測はconst refでのみ適用されます。オブジェクト自体が(参照だけでなく)constとして宣言されている場合、オブジェクトは不変です(誰かが悪意を持ってconstnessをキャストしない限り)。
マシュージェームスブリッグス

4

個人的にconstは、書き込みと読み取りにほとんど時間がかかりません。通常、コードが変数を変更するかどうかを確認するよりもはるかに短い時間で、実際にバグを書き込むことができません(誰かが誤って終了イテレータをインクリメントしたことはありませんか?等)

constの使用法に厳密であることは、重要な初期化を行うヘルパー関数の作成など、他の方法でより良いコードに導くことにも気づきました。


4

他のポスターには同意しないのでconst、ローカル変数とパラメーターにトップレベルを使用しないことをお勧めします。(constへの参照とポインタconst T&は異なります。つまり、適切である場合は常に正確性のためにそれらを使用する必要があります。)

トップレベルの利点constは次のとおりです。

  • ローカル変数が変更されることを意図していないことを明確にします。
  • 誤って変更しようとすると、コンパイラエラーが発生します。

欠点は次のとおりです。

  • 視覚的な混乱。
  • 「疑似定数」変数、つまり直接構築よりも複雑な方法で初期化されているが、後で変更されていない変数では使用できません。例getline

    std::string line; // cannot be const
    std::getline(std::cin, line);
    // line should be const from here on out
  • 関数呼び出しと戻りでの移動最適化を防止します。

    std::string f1();
    std::string f2(std::string s);
    std::string f3() {
      const std::string s = f1(); // s is not meant to be modified
      // but I still want the move optimization here:
      const std::string result = f2(std::move(s)); // this doesn't move
      // and I want the compiler to move out here:
      return result; // this will probably RVO, but if not, the move
                     // constructor will not be used due to the const
    }

私はローカルconstが多く使用されているコードベースで作業しましたが、まったく役に立たないことに気付きましたが、コードは上記のように微妙な悲観化で埋められました。私は個人的には、できるだけ変数を変更せず、変数の使用法が明らかであるほど関数を小さくするという一般的なポリシーを採用します。また、変数が変更されたとしても、関数の複雑さはそれを非-問題。


2
move-fromについてのあなたのポイントは、あなたがローカルでconstの方法で使用していない場所を示しています。これは移動によって(意図して)ローカルを変更するためです
Caleth

1
@Calethいいえ、それがポイントです。変更するつもりはありません。単に値を渡したい、または返したいだけで、効率的にしたいのです。概念的には、変更は単なる最適化であり、観察可能であることを意図していません(変数は後で使用されないため)。実際には、はい。C++には真の破壊的な動きがないため(Rustのように)、変更があります。それがまさに私がconst地元の人に望まない理由です。それはそれが概念的な修正だけでなく、技術的な修正を防ぐからです。
Sebastian Redl 2016年

2
あなたは変更したくない値をしていますが、変更したいん変数を。代わりにconst&を使用し、どちらも変更しないことができます
Caleth

2

constキーワードは、単にパラメータのように、ローカル変数を使用する必要があります。次の理由で便利です。

  • コードを読みやすくする。誰かが変数宣言を読んだとき、彼女はそれが変更されないことを知っています。コードを読むときに心配することは1つ少なくなります。
  • 誤って変数を変更しないようにする
  • 実行時のペナルティはなく、すべてが静的にチェックされます。それは無料の昼食のようで、const書くのにほんの1秒しかかからないので、大したことではありません。
  • マルチスレッドアプリケーションで変数/パラメーターを作成することは常に良い考えです。アプリケーションがマルチスレッド化されていなくても、それは良い習慣です。
  • C ++コンパイラにコードを最適化する機会を与えます。

ここには正解/不正解はありません。あなたのリンクでは、賛成票が最も多かった回答者をfinalローカルで使用しないでください。ただし、次の回答者は強く推奨しました。

関数が単純些細な場合はconst、誰もがあなたの意図を理解しているので、追加しないでください。ただし、関数のロジックが重要な場合は、キーワードを使用する必要があります。失うものはほとんどありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.