web-dev-qa-db-ja.com

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

この質問は Javaのfinalに関する質問 に触発されています。

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

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

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

それで、可能な限りconstを使用する必要がありますか?もしそうなら、なぜC++のconstのアドバイスがJavaのfinalのアドバイスと異なるのですか?

13
ocomfd

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

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

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

18
user22815

個人的には、constを使用すると、書き込みにほとんど時間がかからず、通常、コードが変数を変更しているかどうかを確認するよりもはるかに短い時間で済みます。偶然に最後のイテレータ?など)

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

4
Bwmat

他のポスターには同意しないので、ローカル変数とパラメータにしないでくださいトップレベルの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が頻繁に使用されるコードベースで作業しましたが、まったく役に立たないことに気付きましたが、コードは上記のように微妙な悲観化で埋められました。個人的には、できるだけ変数を変更せず、変数の使用法が明白になるほど関数を小さくするという一般的なポリシーを採用することを好みます。また、変数が変更されても、関数の複雑さは低いため、 -問題。

4
Sebastian Redl

constキーワードは、パラメーターと同様に、ローカル変数に使用する必要があります。次の理由で役立ちます。

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

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

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

2
HelloWorld