151

では、なぜconstをできるだけ頻繁に使用することが常に推奨されているのでしょうか。constを使用することは、C++でのヘルプよりも苦痛になる可能性があるように思われます。しかし、繰り返しになりますが、私はPythonの観点からこれに取り組んでいます。何かを変更したくない場合は、変更しないでください。そうは言っても、ここにいくつかの質問があります:

  1. 何かをconstとしてマークするたびに、エラーが発生し、constになるように他の関数をどこかで変更する必要があるようです。次に、これにより、別の関数を別の場所で変更する必要があります。これは経験を積むだけで簡単になるものですか?

  2. constを使用する利点は、問題を補うのに本当に十分ですか?オブジェクトを変更するつもりがないのなら、それを変更しないコードを書いてみませんか?

現時点では、正確性と保守性の目的でconstを使用することの利点に最も焦点を当てていますが、パフォーマンスへの影響についても理解しておくと便利です。

4

16 に答える 16

170

これは、「const correctness」に関する決定的な記事です: https://isocpp.org/wiki/faq/const-correctness

一言で言えば、 const を使用することは良い習慣です...

  1. 変更する意図のない変数を誤って変更することを防ぎます。
  2. これにより、偶発的な変数の割り当てを防ぐことができます。
  3. コンパイラはそれを最適化できます。たとえば、あなたは次から保護されています

    if( x = y ) // whoops, meant if( x == y )
    

同時に、変数/関数の状態が常に正確にわかっているため、コンパイラはより効率的なコードを生成できます。タイトな C++ コードを作成している場合は、これで十分です。

const-correctness を一貫して使用するのは難しい場合があるという点では正しいですが、終了コードはより簡潔でプログラミングがより安全です。多くの C++ 開発を行うと、この利点がすぐに現れます。

于 2008-09-25T23:40:30.943 に答える
136

これは、constの正当性がユーザーを保護できる一般的なエラーのあるコードです。

void foo(const int DEFCON)
{
   if (DEFCON = 1)     //< FLAGGED AS COMPILER ERROR! WORLD SAVED!
   {
       fire_missiles();
   }
}
于 2008-09-25T23:37:05.100 に答える
67

何かをconstとしてマークするたびに、エラーが発生し、constになるように他の関数をどこかで変更する必要があるようです。次に、これにより、別の関数を別の場所で変更する必要があります。これは経験を積むだけで簡単になるものですか?

経験から、これは完全な神話です。これは、const-correct以外のコードがconst-correctコードと一致する場合に発生します。最初からconst-correctを設計する場合、これが問題になることはありません。何かをconstにした後、他の何かが準拠しない場合、コンパイラは非常に重要なことを通知しているので、時間をかけて適切に修正する必要があります。

于 2008-09-26T00:19:29.583 に答える
33

const を厳密に使用すると、ほとんどの関数で実際の変数が少ないことに驚かれることでしょう。多くの場合、ループ カウンターにすぎません。あなたのコードがその点に達している場合、あなたは内部に暖かい気持ちを感じます...コンパイルによる検証...関数型プログラミングの領域が近くにあります...あなたはほとんどそれに触れることができます...

于 2008-09-27T00:03:11.180 に答える
32

あなたが最初にコードを書いているとき、それはあなたのためではありません。これは、クラスまたはインターフェイス内のメソッド宣言を見て、それが何をするかを確認している他の誰か(または数か月後のあなた)のためのものです。オブジェクトを変更しないことは、そこから収集する重要な情報です。

于 2008-09-25T23:37:59.670 に答える
23

const は、開発者としての約束であり、コンパイラの助けを借りて強制します。

私の const-correct の理由:

  • 関数のクライアントに、変数またはオブジェクトを変更しないことを伝えます
  • const 参照によって引数を受け入れると、値渡しの安全性とともに参照渡しの効率が得られます。
  • インターフェイスを const correct として記述すると、クライアントがそれらを使用できるようになります。非 const 参照を受け取るようにインターフェイスを作成する場合、const を使用しているクライアントは、あなたと連携するために constness をキャストする必要があります。インターフェイスが非 const char* を受け入れ、クライアントが std::strings を使用している場合、これは特に厄介です。これは、それらから const char* しか取得できないためです。
  • const を使用すると、変更すべきではないものを誤って変更しないように、コンパイラが誠実さを保つようになります。
于 2008-09-26T02:24:55.710 に答える
22

constなしでC++をプログラミングすることは、安全ベルトを着用せずに運転するようなものです。

車に乗るたびにシートベルトを着用するのは面倒で、365日のうち364日で無事に到着します。

唯一の違いは、車に問題が発生するとすぐにそれを感じることですが、constを使用しないプログラミングでは、クラッシュの原因を2週間検索する必要があり、関数の引数を誤って台無しにしたことがわかります。効率のために非定数参照を渡しました。

于 2008-09-26T08:00:52.330 に答える
21

私の哲学は、コンパイル時のチェックで細かいことを気にする言語を使用する場合は、それを最大限に活用することです。 あなたが意味するconstことを伝えるコンパイラ強制の方法です...コメントやdoxygenよりも優れています。あなたは代価を払っているのに、価値を導き出さないのはなぜですか?

于 2008-09-26T00:54:20.703 に答える
20

組み込みプログラミングのconst場合、グローバル データ構造を宣言するときに を慎重に使用すると、定数データが​​起動時に RAM にコピーされずに ROM またはフラッシュに配置されるため、大量の RAM を節約できます。

日常のプログラミングでは、const慎重に を使用することで、文字列リテラルやその他の定数グローバル データを変更しようとするためにクラッシュしたり、予期せぬ動作をするプログラムを作成することを避けることができます。

大規模なプロジェクトで他のプログラマーと一緒に作業する場合、const適切に使用することで、他のプログラマーがあなたを抑圧するのを防ぐことができます。

于 2008-09-26T03:30:20.890 に答える
15

const の正確性は、最初から適切に配置する必要があるものの 1 つです。お気づきのように、後で追加するのは非常に面倒です。特に、追加する新しい関数と既に存在する古い非 const-correct 関数との間に多くの依存関係がある場合はなおさらです。

私が書いた多くのコードでは、合成を多用する傾向があるため、本当に努力する価値がありました。

class A { ... }
class B { A m_a; const A& getA() const { return m_a; } };

const-correctness がなければ、背後で誰もクラス B の内部状態を操作していないことを確認するために、複雑なオブジェクトを値で返すことに頼る必要があります。

要するに、const-correctness は、将来の苦痛から身を守るための防御的なプログラミング メカニズムです。

于 2009-12-09T02:40:20.023 に答える
13

const背後で「物事を変更する」コードを分離するのに役立ちます。したがって、クラスでは、オブジェクトの状態を変更しないすべてのメソッドを としてマークしますconst。これは、そのクラスのインスタンスが非メソッドconstを呼び出すことができなくなることを意味します。constこのようにして、オブジェクトを変更できる機能を誤って呼び出すことを防ぎます。

また、constオーバーロード メカニズムの一部であるため、同一のシグネチャを持つ 2 つのメソッドを使用できますが、1 つはconstあり、もう 1 つはなしです。付きのものconstconst参照用に呼び出され、もう 1 つは非const参照用に呼び出されます。

例:

#include <iostream>

class HelloWorld {
    bool hw_called;

public:
    HelloWorld() : hw_called(false) {}

    void hw() const {
        std::cout << "Hello, world! (const)\n";
        // hw_called = true;  <-- not allowed
    }

    void hw() {
        std::cout << "Hello, world! (non-const)\n";
        hw_called = true;
    }
};

int
main()
{
    HelloWorld hw;
    HelloWorld* phw1(&hw);
    HelloWorld const* phw2(&hw);

    hw.hw();    // calls non-const version
    phw1->hw(); // calls non-const version
    phw2->hw(); // calls const version
    return 0;
}
于 2008-09-25T23:45:13.660 に答える
7

Python に変数があるとします。あなたはそれを変更することになっていないことを知っています。うっかりしてしまったら?

C++ は、そもそも実行できないはずのことを誤って実行してしまうことから身を守る方法を提供します。とにかく技術的には回避できますが、自分を撃つには余分な作業が必要です。

于 2008-09-26T03:46:24.283 に答える
4

ここにC++のconstに関する素晴らしい記事があります。それはかなり率直な意見ですが、それがいくつかの助けになることを願っています。

于 2008-09-25T23:37:30.607 に答える
3

「const」キーワードを使用すると、クラスに別のインターフェイスを指定します。すべてのメソッドを含むインターフェイスと、const メソッドのみを含むインターフェイスがあります。明らかに、これにより、変更したくないものへのアクセスを制限できます。

はい、時間の経過とともに簡単になります。

于 2008-09-26T00:07:01.597 に答える
2

私は const の正しさが好きです...理論的には。実際に厳密に適用しようとするたびに、最終的には機能しなくなり、コードを醜くするために const_cast が忍び寄り始めます。

私が使っているデザインパターンだけかもしれませんが、 const はいつも広すぎます。

たとえば、単純なデータベース エンジンを想像してみてください...スキーマ オブジェクト、テーブル、フィールドなどがあります。ユーザーは、テーブル スキーマ自体の変更が許可されていないことを意味する「const Table」ポインタを持っている場合があります...しかし、操作はどうでしょうか。テーブルに関連付けられたデータ? Insert() メソッドが const とマークされている場合、実際にデータベースを操作するには、内部的に const 性をキャストする必要があります。const とマークされていない場合、AddField メソッドの呼び出しから保護されません。

おそらく答えは、const-ness 要件に基づいてクラスを分割することですが、それは、それがもたらす利点に対して私が望む以上に設計を複雑にする傾向があります。

于 2008-09-26T00:01:19.083 に答える
1

const を使用してコンパイラのヒントを与えることもできます....次のコードのように

#include <string>

void f(const std::string& s)
{

}
void x( std::string& x)
{
}
void main()
{
    f("blah");
    x("blah");   // won't compile...
}
于 2008-09-26T03:59:30.647 に答える