これが適切かどうかを確認してください。ただし、標準MLのような関数型言語では、すべてがデフォルトで不変です。突然変異は、一般的なrefエレンスタイプによってサポートされます。したがって、int変数は不変であり、ref int変数はintsの可変コンテナーです。基本的に、変数は数学的な意味での実際の変数(未知ではあるが固定値)であり、refsは命令型プログラミングの意味での「変数」です-読み書き可能なメモリセルです。(私はそれらをassignablesと呼ぶのが好きです。)
問題constは2つあると思います。まず、C ++にはガベージコレクションがありません。これは、重要な永続データ構造を持つために必要です。意味をなすためには深くconst なければなりませんが、C ++で完全に不変の値を持つことは実用的ではありません。
次に、C ++ constでは、オプトアウトするのではなくオプトインする必要があります。しかし、const何かを忘れて後で修正すると、@ RobYの回答で言及されている「const poisoning」状況に陥りconst、コード全体に変更がカスケードされます。場合はconstデフォルトだった、あなたは適用自分自身を見つけることができませんでしょうconst遡及。さらに、constどこにでも追加する必要があるため、コードに多くのノイズが追加されます。
後に続いた主流言語(Javaなど)は、CとC ++の成功と考え方によって大きく形作られたのではないかと思います。適切な例として、ガベージコレクションを使用しても、ほとんどの言語のコレクションAPIは可変データ構造を想定しています。すべてが可変で不変であるという事実は、一例として一般的な言語の背後にある命令的な考え方について多くを語っています。
編集:greenoldmanのコメントを反映した後const、データの不変性に関するものではないことに気付きました。constインスタンスに副作用があるかどうかをメソッドの型にエンコードします。
参照透過的な動作を実現するために突然変異を使用することは可能です。連続して呼び出されたときに異なる値を返す関数があるとします。たとえば、から単一の文字を読み取る関数などですstdin。この関数の結果をキャッシュ/メモ化して、参照的に透過的な値のストリームを生成できます。ストリームはリンクされたリストになり、ノードは値を最初に取得しようとしたときに関数を呼び出しますが、結果をキャッシュします。あればstdinconstains Hello, world!、あなたが最初のノードの値を取得しようとする最初の時間は、それが1を読んであげるcharと返しますH。その後H、aを読むためのさらなる呼び出しなしで戻り続けますchar。同様に、第2のノードは、読んでいましたcharからstdin最初にその値を取得しようとすると、今回はeその結果を返し、キャッシュします。
ここで興味深いのは、本質的にステートフルなプロセスを、ステートレスに見えるオブジェクトに変えたことです。ただし、これを実現するには、オブジェクトの内部状態を(結果をキャッシュすることによって)変更する必要がありました。この変更は良性の効果でした。CharStream constストリームが不変の値のように動作する場合でも、作成することはできません。ここでStream、constメソッドを備えたインターフェースがあり、すべての関数がを期待してconst Streamsいると想像してください。あなたは、CharStreamインターフェイスを実装することはできません!
(EDIT 2:どうやらキーワードと呼ばれるC ++がありますmutableことを、私たちは、カンニングやメイクできるようになるCharStream constしかし、この抜け穴を破棄します。constの保証は-今、あなたは本当に何かがのmutateそのを通じてません確認することはできませんconst方法私はそれがあることではないと仮定します。あなたは明示的に抜け穴を要求しなければならないので悪いですが、あなたはまだ名誉制度に完全に依存しています)
次に、高階関数があると仮定します。つまり、関数を引数として他の関数に渡すことができます。constnessは関数のシグネチャの一部であるためconst、関数を期待するconst関数の引数として非関数を渡すことはできません。constここで盲目的に強制すると、一般性が失われます。
最後に、constオブジェクトを操作しても、背後にある外部(静的またはグローバル)状態が変化しconstないことは保証されません。
副作用の有無を型システムにエンコードすることが普遍的に良いことであることは私には明らかではありません。