文字列は不変ですが、なぜすべてが定数ではないのですか?


8

stringタイプは不変です。

.NETのような高級言語でconstキーワードを使用できstringsます。'const'についての私の理解は一定を意味します(同じままで、値を変更することはできません)。

strings常にではありませんかconstant(IMOの用語constantは、値のライフタイムを意味するたびに型を再作成する必要がある場合、同じコンテキストでは適用できません)、それは一定でした)?

高水準言語、特に.NET(私もJavaに興味があります)では、これはオブジェクトの一般的なメモリ管理/追跡によるものですか、それとも別の理由がありますか?


6
どのプログラミング言語を使用していますか?答えは、言語の実装の具体的な詳細によって異なります。
ViliamBúr2013年

「定数」の定義を理解するのは困難です。「一度作成すると常に存在する」という意味ですか?はいの場合、答えは明白です。メモリが不足します。
パルジファル2013年

1
それがあなたの言いたいことではない場合は、オブジェクトとそれらを指す変数が混乱しています。Javaの "定数"(および.Netも想定しています)は、決して変更できない変数です。
パルジファル2015年

1
@DaveRook Javaでは、final文字列変数の修飾子は、変数が別の文字列を指すように変更されるのを防ぎます。

1
定数にする必要があるもの、変更できないもの:特定の文字列オブジェクトの文字、または特定の変数のオブジェクト?それは2つの異なることです。Javaでは、文字列は不変です。つまり、文字列オブジェクトを作成した場合、それ変更することはできません ...しかし、それ破棄して、別のオブジェクトを同じ変数に入れることができます。定数文字列(Javaでは「静的な最終文字列」)は、変数内のオブジェクトを置き換えることさえできないことを意味します。
ViliamBúr2013年

回答:


22

あなたは2つの異なるものを混乱させています:

  • 不変とは、オブジェクトのメモリの内容を変更できないことを意味します。不変オブジェクト(aなどstring)を変更しても、このオブジェクトのメモリの内容は変更されません。代わりに:

    1. 新しいメモリのブロックが割り当てられています。
    2. 変更した(試行した)オブジェクトの内容がこの新しいブロックにコピーされ、変更したい部分がこの新しいブロックで変更されます。
    3. ポインタ(つまり、参照)がこの新しいブロックに割り当てられます。
  • 定数とは、コンパイル時に変数を変更できないことを意味します。かstringまたはinteger変数(または何それが指す)の内容が変更またはコンパイル時に割り当てることができません。


ありがとうございました。私は文字通り遠くにいますが、これはそれをうまく答えます。
Dave

1
コンパイル時に定数を変更できない場合、いつ変更しますか?
パルジファル2015年

2
もしそうであれば@parsifal constあなたがすることはできませんそれを修正します。初期値に定義することはできますが、他の場所に別の値を割り当てることはできないため、変更することはできません。
rae1 2013年

@ rae1n:これは100%正しくありません。定数は、変数をランタイムで変更できないことを意味します。これは文字列を保持する変数のプロパティですが、不変性はオブジェクト自体のプロパティです。
Doc Brown

@DocBrownコンパイル時に定数を変更できると言っていますか?
rae1 2013年

6

コメントが言うように、「定数」と「不変」を混同しているのは、それらが本当に2つの非常に異なることを意味している場合です。

定数は、ある変数を変更することはできません。言語とコンパイラによっては、コンパイルされたコードがその変数のすべての使用をそれに割り当てられた値で単純に置き換えることが完全に可能です。その場合、メモリ内のスポットに割り当てられることすらありません。コンパイラーがそのように最適化しない場合でも、コンパイラーは起動時にメモリー内に1つのスポットを割り当て(をconst意味するためstatic)、終了するまでそこにとどまります。

不変であるメモリの値(メモリが再利用されるまで)変更することができません。必要に応じてメモリ内の場所が割り当てられ、(理論的には)複数の変数に格納できます。不変値を指す変数に割り当てると、単に新しい不変変数が作成され、代わりにその変数を指すように変数が変更されます。古い値は、ガベージコレクションが行われるまでメモリに残ります。これは、プログラムの実行中でも発生する可能性があります。


3
定数が実際に行っていることを説明するための+1:参照されるすべての場所で変数の値をインライン化します。これは、ここで述べたものよりもさらに大きな効果があるため、理解する重要なメカニズムです。
ジミーホファ2013年

2

文字列は変更できません。 文字列へのポインタ変更できます。以下は有効なコードです。

String text = "Text";
text = text.substring(1);

元の「Text」オブジェクトはまだ存在し、変更されておらず、不変ですが、何も指していません。ミュータブルStringを使用するとtext.substring(1)text変数に再度割り当てる必要がなく、元のオブジェクトが変更されます。変数 textを変更しない場合は、それをに変更しますconst。両方に有効なユースケースがあります。

補足として、これはC ++で理解しやすい概念の良い例です。これは、オブジェクトとオブジェクトへのポインターの型が異なるためです。


1

変数とオブジェクトを混同していると思います。

変数は、単に参照するオブジェクト

プログラムの実行中、変数は複数のオブジェクトを参照できます。変数に何かを割り当てても、オブジェクトは変更されません。オブジェクトを参照する変数がない場合は、ゴミになります。

オブジェクトStringを変更する方法がないため、A は不変と見なされます(Javaでは、.Netでも期待されます)

定数は、単にプログラムの期間中に変更が許可されていない変数です。finalJavaではconst修飾子、.Net では修飾子を使用して定数を定義します。

ただし、「定数」変数が可変オブジェクトを指している場合、変数の「定数」はオブジェクトの可変性に影響を与えません(実際、.Netではそれを確実に言えないので、 C ++の難解なルールの一部を継承しています)。


@Downvoter-コメントしていただけますか?それとも変数とオブジェクトの違いがわからないと思いますか?

1
私はダウンボーターではありませんが、JavaやC#がすべてではないのではないでしょうか。
Ingo

1
@Igno-確かに、OPが「具体的には.NET(Javaに興味があります)」と言ったので、コメントをこれら2つに限定しました。つまり、変数とオブジェクトの分離は、JavaScript、Ruby、Pythonにも適用されます、PerlやPHPと実際には、C ++以外の、私は、クレームは、オブジェクト指向であることをことを他の近代的な言語を考えることはできません。しないこの区別を行う。
パルジファル

-1

何がconst成し遂げられるかの簡単なデモンストレーション。これは、C#および類似の言語に適用されます。

string noconst = "foo";
noconst = "bar"; //noconst has changed! It was declared as "foo" but now is "bar"

const string yesconst = "foo";
yesconst = "bar"; //compiler error

1
これはconst動作を示していますが、動作はに固有のものではありませんconst。Javaでは、finalキーワードは同じように動作し、C#では同じように動作しreadonlyます。aのユニークな点は、constコンパイル時に認識されることです。
コービン3
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.