Một chuỗi là bất biến, vậy tại sao chúng không phải là tất cả các hằng số?


8

Các stringloại là không thay đổi.

Chúng ta có thể sử dụng consttừ khóa với stringsngôn ngữ cấp cao như .NET. Sự hiểu biết của tôi về 'const' có nghĩa là không đổi (nó vẫn giữ nguyên, chúng ta không thể thay đổi giá trị).

Không stringsphải luôn luôn constant(IMO thuật ngữ constantkhông nên được áp dụng trong cùng một bối cảnh nếu loại phải được tạo lại mỗi lần nó có nghĩa là cho các giá trị thời gian sống, nó không đổi)?

Trong các ngôn ngữ cấp cao, cụ thể là .NET (mặc dù tôi cũng quan tâm đến Java), điều này có phải do quản lý / theo dõi bộ nhớ chung của các đối tượng hay còn lý do nào khác?


6
Bạn sử dụng ngôn ngữ lập trình nào? Câu trả lời có thể phụ thuộc vào chi tiết cụ thể của việc thực hiện ngôn ngữ.
Viliam Búr

Định nghĩa của bạn về "hằng" là khó hiểu. Bạn có nghĩa là "một khi được tạo ra nó luôn tồn tại"? Nếu có, câu trả lời sẽ rất rõ ràng: bạn sẽ hết bộ nhớ.
phân tích

1
Nếu đó không phải là ý bạn, thì bạn đang nhầm lẫn các đối tượng và các biến trỏ đến chúng. Một "hằng số" trong Java (và tôi giả sử .Net cũng vậy) chỉ đơn giản là một biến không bao giờ có thể thay đổi.
phân tích

1
@DaveRook Trong Java, công cụ finalsửa đổi trên biến chuỗi ngăn không cho biến được thay đổi để trỏ đến một chuỗi khác.

1
Chính xác những gì cần phải là hằng số , chính xác những gì không thể được sửa đổi: các ký tự trong một đối tượng chuỗi cụ thể hoặc một đối tượng trong một biến cụ thể? Đó là hai điều khác nhau. Trong Java, các chuỗi là bất biến , có nghĩa là khi bạn tạo một đối tượng chuỗi, bạn không thể sửa đổi nó ... nhưng bạn có thể vứt nó đi và đặt một đối tượng khác vào cùng một biến. Chuỗi không đổi ("Chuỗi cuối cùng tĩnh" trong Java) có nghĩa là bạn thậm chí không thể thay thế đối tượng trong biến.
Viliam Búr

Câu trả lời:


22

Bạn đang nhầm lẫn hai điều khác nhau:

  • Bất biến có nghĩa là nội dung bộ nhớ của đối tượng không thể được sửa đổi. Khi bạn sửa đổi một đối tượng bất biến (ví dụ: a string), nội dung bộ nhớ của đối tượng này không được sửa đổi. Thay thế:

    1. Một mới khối bộ nhớ được phân bổ.
    2. Nội dung của đối tượng bạn (đã cố gắng) sửa đổi được sao chép vào khối mới này, với phần bạn muốn thay đổi được thay đổi trong khối mới này.
    3. Con trỏ (nghĩa là tham chiếu) được gán cho khối mới này.
  • Hằng số có nghĩa là biến không thể được sửa đổi tại thời gian biên dịch. Cho dù một stringhoặc một integernội dung của biến (hoặc những gì nó trỏ đến) không thể được thay đổi hoặc gán vào thời gian biên dịch.


Cảm ơn bạn. Tôi đang ở xa nghĩa đen nhưng điều này trả lời nó rất tốt.
Dave

1
Nếu bạn không thể sửa đổi hằng số tại thời gian biên dịch, khi nào bạn sửa đổi nó?
phân tích

2
@parsifal Nếu là constbạn không thể sửa đổi nó. Bạn có thể định nghĩa nó thành một giá trị ban đầu, nhưng bạn không thể gán một giá trị khác cho nó ở bất kỳ nơi nào khác, do đó bạn không thể sửa đổi nó.
rae1

@ rae1n: điều này không đúng 100%. Hằng có nghĩa là một biến không thể được sửa đổi thời gian chạy . Nó là một thuộc tính của biến chứa một chuỗi, trong khi bất biến là một thuộc tính của chính đối tượng.
Doc Brown

@DocBrown Bạn có nói rằng bạn có thể sửa đổi Hằng số tại thời gian biên dịch không?
rae1

6

Như các ý kiến ​​nói, bạn nhầm lẫn "không đổi" với "bất biến", khi chúng thực sự có nghĩa là hai điều rất khác nhau.

Một hằng số là một biến không thể thay đổi. Tùy thuộc vào ngôn ngữ và trình biên dịch, mã biên dịch hoàn toàn có thể thay thế mọi cách sử dụng biến đó bằng giá trị được gán cho nó, trong trường hợp đó, nó thậm chí sẽ không bao giờ được cấp phát một vị trí trong bộ nhớ. Ngay cả khi trình biên dịch không tối ưu hóa theo cách đó, nó vẫn được phân bổ một vị trí trong bộ nhớ khi khởi chạy (kể từ khi constngụ ý static) và ở đó cho đến khi thoát.

Một bất biến là một giá trị trong bộ nhớ không thể thay đổi (cho đến khi bộ nhớ được lấy lại). Nó được chỉ định một vị trí trong bộ nhớ khi cần thiết và về mặt lý thuyết có thể được lưu trữ trong nhiều biến. Việc gán cho một biến chỉ vào một giá trị bất biến chỉ đơn giản là tạo ra một bất biến mới và thay đổi biến để trỏ đến đó. Giá trị cũ lưu lại trong bộ nhớ cho đến khi rác được thu thập, điều này có thể xảy ra ngay cả khi chương trình đang chạy.


3
+1 để giải thích hằng số thực sự đang làm gì: nội tuyến giá trị của biến của bạn ở mọi nơi mà nó được tham chiếu; đó là một cơ chế quan trọng để hiểu vì nó thậm chí còn có tác dụng lớn hơn những gì được đề cập ở đây.
Jimmy Hoffa

2

Chuỗi không thể thay đổi. Con trỏ đến chuỗi có thể thay đổi. Sau đây là mã hợp lệ:

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

Đối tượng "Văn bản" ban đầu vẫn còn đó, không thay đổi và không thay đổi, ngoại trừ không có gì chỉ vào nó nữa. Một biến đổi Stringsẽ cho phép bạn làm text.substring(1)mà không cần phải gán lại cho textbiến đó và nó sẽ thay đổi đối tượng ban đầu. Nếu bạn muốn biến text không thay đổi, đó là khi bạn thực hiện nó const. Có trường hợp sử dụng hợp lệ cho cả hai.

Một lưu ý phụ, đây là một ví dụ hay về khái niệm dễ hiểu hơn trong C ++, bởi vì các đối tượng và con trỏ tới các đối tượng có các loại khác nhau.


1

Tôi tin rằng bạn đang nhầm lẫn các biến và đối tượng.

Một biến chỉ đơn giản là một tham chiếu đến một đối tượng .

Trong khi chương trình của bạn đang chạy, một biến có thể tham chiếu đến nhiều đối tượng . Việc gán một cái gì đó cho biến không làm thay đổi đối tượng. Nếu không có biến tham chiếu đến một đối tượng, nó sẽ trở thành rác.

A Stringđược coi là bất biến (trong Java và tôi cũng mong đợi ở .Net) vì không có cách nào để thay đổi đối tượng .

Một hằng số chỉ đơn giản là một biến mà không được phép thay đổi trong suốt cuộc đời của chương trình. Bạn xác định một hằng số với công cụ finalsửa đổi trong Java và công cụ constsửa đổi trong .Net.

Tuy nhiên, nếu biến "hằng" của bạn trỏ đến một đối tượng có thể thay đổi, thì "hằng số" của biến đó không ảnh hưởng đến khả năng biến đổi của đối tượng (thực ra, tôi không thể nói điều đó chắc chắn trong .Net, vì tôi giả sử nó kế thừa một số quy tắc phức tạp của C ++).


@Downvoter - bạn có muốn bình luận không? Hay tôi nên cho rằng bạn cũng không biết sự khác biệt giữa một biến và một đối tượng?
phân tích

1
Tôi không phải là người xuống cấp - nhưng bạn có nghĩ rằng không phải tất cả thế giới là Java hay C # không?
Ingo

1
@Igno - chắc chắn, ngoại trừ OP đã nói "cụ thể là .NET (mặc dù tôi rất quan tâm đến Java" nên tôi đã giới hạn nhận xét của mình cho hai thứ đó. Điều đó nói rằng, sự tách biệt giữa biến và đối tượng cũng áp dụng cho JavaScript, Ruby, Python , Perl và PHP. Trên thực tế, ngoài C ++, tôi không thể nghĩ ra một ngôn ngữ hiện đại khác tự
xưng

-1

Một minh chứng đơn giản về những gì đi constkèm. Điều này được áp dụng cho C # và các ngôn ngữ tương tự.

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
Trong khi điều này cho thấy cách constcư xử, hành vi không phải là duy nhất const. Trong Java, finaltừ khóa hoạt động tương tự và trong C #, readonlytừ khóa cũng làm như vậy. Điều độc đáo về a constlà nó được biết đến vào thời gian biên dịch.
Corbin ngày
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.