Tại sao bạn nên sử dụng từ khóa const nếu bạn đã biết biến không đổi?


67
7
Võ Tâm Thiện
6 năm trước

Nhiều cuốn sách mà tôi đang đọc sử dụng từ khóa constkhi giá trị của một biến không nên được sửa đổi. Ngoài việc chỉ định cho người đọc mã rằng bạn có thể gây ra lỗi nếu bạn sửa đổi biến này (bạn có thể sử dụng nhận xét để làm điều này), tại sao bạn cần từ khóa đó là một phần của bất kỳ ngôn ngữ lập trình nào? Dường như với tôi rằng nếu bạn không muốn một biến được sửa đổi, đơn giản là không.

Ai đó có thể làm rõ điều này cho tôi?

Hữu ích 67 Yêu thích 7 Chia sẻ Viết bình luận 5
Không hữu ích

Bỏ qua constsẽ làm việc rất tốt cho các lập trình viên không bao giờ phạm sai lầm.

Hữu ích 71 · Không hữu ích · Trả lời 0

Tại sao sử dụng bảo vệ hoặc tư nhân? Hay trừu tượng? Hay cuối cùng?

Hữu ích 41 · Không hữu ích · Trả lời 0

Khi thực hiện lập trình hệ thống nhúng, việc có một trình constxác định sẽ cung cấp trình biên dịch và trình liên kết tùy chọn ánh xạ địa chỉ của giá trị vào phần bộ nhớ EPROM thay vì trong RAM. Tôi đã làm việc trên một hệ thống nhiều năm trước có hành vi này đối với các biến tĩnh được gán trước (trước khi consttừ khóa được giới thiệu).

Hữu ích 33 · Không hữu ích · Trả lời 0

Stroustrup đặt nó tốt nhất: trình biên dịch không đọc bình luận. Có thể bạn nghĩ rằng bạn giỏi theo các quy tắc hơn là một trình biên dịch.

Hữu ích 26 · Không hữu ích · Trả lời 0

Hãy nhớ rằng có rất nhiều từ khóa và khái niệm có sẵn để giúp các lập trình viên, không phải các chương trình. constlà một chút của cả hai.

Hữu ích 8 · Không hữu ích · Trả lời 0

11 Trả lời


97
Lê Thi Xuân
6 năm trước

Ngoài việc chỉ định cho người đọc mã mà bạn có thể gây ra lỗi nếu bạn sửa đổi biến này (bạn có thể sử dụng nhận xét để làm điều này)

Không "may"; sẽ gây ra lỗi trong chương trình của bạn.

  • Trình biên dịch C ++ sẽ thực thi nó với các lỗi biên dịch và thông báo chẩn đoán ("lỗi trình biên dịch"), không cần bình luận;
  • Trình biên dịch AC sẽ thực thi phần lớn , mặc dù thư viện tiêu chuẩn của nó có lỗ hổng nhờ vào di sản, chẳng hạn như strchr, và nó có một số quy tắc chuyển đổi ngầm khá khoan dung có thể cho phép bạn bỏ qua constmà không nhận ra nó khá dễ dàng. Tuy nhiên, chỉ vì bạn có một bản biên dịch thành công không có nghĩa là bạn không có lỗi; thật không may, điều đó có nghĩa là các lỗi có thể là các lỗi tinh vi trong chương trình của bạn, cũng như các sự cố lớn, ngoạn mục.

Dù bằng cách nào, chương trình của bạn được đảm bảo có lỗi bên trong nó.

Dường như với tôi rằng nếu bạn không muốn một biến được sửa đổi, đơn giản là không.

Vâng, đó là tất cả tốt và tốt, nhưng không ai hoàn hảo. Lập trình viên mắc lỗi. Điều này cho phép trình biên dịch - không bao giờ mắc lỗi (ít nhất, không thường xuyên) - chỉ ra chúng cho bạn.

Nó được sử dụng cụ thể khi bạn đang sử dụng một số biến dữ liệu nhiều, nhiều dòng mã cách xa nơi nó được tạo. Càng đi xa, bạn càng dễ dàng sửa đổi nó mà không nhận ra rằng bạn không được phép. Đối với các cơ sở mã lớn, phức tạp, nó chỉ đơn giản là phải.

Bạn nhận được một thước đo mới về tính dễ chứng minh , tính chính xáctính ổn định trong cơ sở mã của mình, cũng như một phần lớn các nguyên nhân có thể gây ra các lỗi thực sự tinh vi và khó chịu. Ngoài ra còn có các cơ hội tối ưu hóa lớn cho trình biên dịch của bạn (trong một số trường hợp) khi biết rằng một số giá trị sẽ không thay đổi sau khi biên dịch.

Chúng ta có thể liệt kê những lợi thế cả ngày nhưng, thực sự, bạn sẽ không hoàn toàn grok nó cho đến khi bạn đã làm việc trên một codebase như vậy.

Trong thực tế, trong một thế giới hoàn hảo, tất cả các biến sẽ consttheo mặc định và bạn cần khai báo chúng bằng từ khóa mutableđể có thể thay đổi chúng. C ++ là ngược.

Hữu ích 97 Chia sẻ Viết bình luận 5
Không hữu ích

"Trong một thế giới hoàn hảo, tất cả các biến sẽ được cấu thành theo mặc định": chúng có được gọi là bất biến không?

Hữu ích 21 · Không hữu ích · Trả lời 0

@ouah: Scala không thực sự là thế giới hoàn hảo. Nó khuyến khích sự bất biến. Haskell (cho một ví dụ) thi hành nó.

Hữu ích 20 · Không hữu ích · Trả lời 0

Tôi muốn sống trong thế giới hoàn hảo đó!

Hữu ích 17 · Không hữu ích · Trả lời 0

+1. Sau một số kinh nghiệm với Haskell và lập trình đồng thời, tôi đã đi đến cùng một kết luận "tất cả các biến sẽ được tạo theo mặc định" . Trong thực tế, nó là không chắc chắn về mặt triết học nếu một biến có thể thay đổi theo mặc định . Nó có cùng một vấn đề triết học nếu các thành viên của một lớp được công khai theo mặc định .

Hữu ích 2 · Không hữu ích · Trả lời 0

Scala là thế giới hoàn hảo này: tính bất biến được khuyến khích, các lớp bộ sưu tập là bất biến theo mặc định và bạn cần một từ khóa cụ thể varđể khai báo các biến không biến đổi.

Hữu ích 1 · Không hữu ích · Trả lời 0

40
Trần Mộng Ðiệp
6 năm trước

Ít nhất là trong C ++, constcó một số cách sử dụng ngoài việc ghi lại ý định của bạn cho các lập trình viên khác.

constcũng có thể nói cho trình biên dịch một số điều. Ví dụ: một hàm lấy tham chiếu, như: void f(T &t);không thể chấp nhận một đối tượng tạm thời làm tham số. Để có được nó để làm như vậy, bạn cần phải constđủ điều kiện tham khảo, như : void f(T const &t).

Tương tự, để gọi một hàm thành viên trên một đối tượng const, hàm thành viên phải constđủ điều kiện như : void T::foo() const {}.

Trong một hệ thống nhúng, const có thể có nghĩa là tĩnh hơn, có thể nói cho trình biên dịch biết vị trí của đối tượng được đề cập (đặt nó trong ROM so với RAM). consttự nó không nhất thiết phải nói với nó "đưa đối tượng này vào ROM", nhưng nó vẫn thường là điều kiện tiên quyết.

Tương tự như vậy (theo C ++ 11) const cho trình biên dịch về an toàn luồng .

Bây giờ, chắc chắn đúng là bạn có thể định nghĩa một số ngôn ngữ khác (theo những cách khác) mang một số điểm tương đồng với C hoặc C ++ không sử dụng consttheo những cách này. Kết quả sẽ là một ngôn ngữ khá khác với một trong hai. Không biết ý định của bạn, không thể nói nó sẽ diễn ra như thế nào, nhưng nó có thể kết thúc gần hơn với Java hoặc C # (đối với một vài ví dụ) cả hai đều tương tự như C và C ++ theo một số cách, nhưng không phải vậy một (nghĩa là không sử dụng constnhư C và C ++).

Hữu ích 40 Chia sẻ Viết bình luận 1
Không hữu ích

Java hoàn toàn không sử dụng const, nếu tôi nhớ lại. (Tôi nghĩ đó là một từ dành riêng, nhưng không thể sử dụng cho bất cứ điều gì.) finalTừ khóa của nó tương tự nhưng không hoàn toàn giống nhau. C # có const, nhưng nó không giống nhau. (Tôi nghĩ rằng nó hầu như chỉ tương đương với #defines.)

Hữu ích 0 · Không hữu ích · Trả lời 0

36
Phạm Thanh Phong
6 năm trước

Bên cạnh những cân nhắc lập trình thông thường đã được thảo luận trong các câu trả lời khác, một điều khiến tôi quan tâm là thái độ:

Dường như với tôi rằng nếu bạn không muốn một biến được sửa đổi, đơn giản là không.

Một nguyên tắc chung là 20% chi phí viết mã được sử dụng trong giai đoạn phát triển. 80% khác được sử dụng trong suốt vòng đời của mã để nâng cấp nó, duy trì nó, v.v. Điều này có nghĩa là nhiều người khác sẽ làm việc với mã của bạn chứ không phải chính bạn.

Thời gian dành cho quá trình phát triển để tránh các vấn đề nhiều năm sau đó là một khoản đầu tư tốt. Nỗ lực này bao gồm: viết bình luận; xác định các hằng số là hằng số; và viết mã rõ ràng không dựa trên các cấu trúc ngôn ngữ tối nghĩa.

Ngoài ra, @worlboss, tôi nghe thấy một sự không khoan dung. Như một số người khác đã nhận xét, các đơn vị carbon mắc lỗi và bất cứ điều gì một đơn vị silicon có thể làm để giúp tránh sai lầm được đánh giá cao.

Hữu ích 36 Chia sẻ Viết bình luận 4
Không hữu ích

+1 để đề cập đến 80% trong bảo trì mà hầu hết mọi người đều quên.

Hữu ích 9 · Không hữu ích · Trả lời 0

@JackCColeman, tôi đã nói rằng 20% ​​có vẻ cao. Tôi nghĩ rằng nó gần giống như 10

Hữu ích 1 · Không hữu ích · Trả lời 0

20% đó có vẻ cao. Nó có thể là 20% nếu tất cả những điều đúng đã được thực hiện ngay từ đầu. Thật không may, điều đó dường như không luôn xảy ra.

Hữu ích 0 · Không hữu ích · Trả lời 0

@ user606723, đó là quy tắc của ngón tay cái. Nếu giai đoạn phát triển có chi phí cao hơn kế hoạch thì 20% sẽ tăng theo một phần của tổng chi phí trọn đời của phần mềm.

Hữu ích 0 · Không hữu ích · Trả lời 0

21
Đặng Ngọc Uyên
6 năm trước

Nó báo cho trình biên dịch rằng biến không nên được sửa đổi, vì vậy nếu ai đó viết mã sửa đổi nó, trình biên dịch sẽ đánh dấu nó là một lỗi.

Hữu ích 21 Chia sẻ Viết bình luận 1
Không hữu ích

Tôi cá rằng các lợi ích liên quan đến hiệu suất cũng rất quan trọng tại thời điểm này xuất hiện.

Hữu ích 2 · Không hữu ích · Trả lời 0

17
Phạm Thùy Vân
6 năm trước

Hai lý do:

  1. trình biên dịch tài liệu thi hành
  2. tối ưu hóa trình biên dịch

Dưới đây là một lời giải thích tốt từ Ian Lance Taylor (người đã làm việc gccgoldliên kết):

Ý nghĩa đầu tiên của const có ảnh hưởng thực sự đến chương trình. Một biến được khai báo const có thể được biên dịch khác với một biến không được khai báo const.

Mặt khác, ý nghĩa thứ hai của const là tài liệu được thực thi bởi trình biên dịch. Trình biên dịch sẽ đưa ra lỗi nếu một nỗ lực được thực hiện để thay đổi giá trị bằng cách sử dụng con trỏ đủ điều kiện const, nhưng khai báo một con trỏ như vậy sẽ không thay đổi mã được tạo.

Hữu ích 17 Chia sẻ Viết bình luận 5
Không hữu ích

[C++11: 8.3.5/3]: [..] Sau khi tạo danh sách các loại tham số, mọi bộ định mức cv cấp cao nhất sửa đổi loại tham số sẽ bị xóa khi hình thành loại chức năng . [..]

Hữu ích 3 · Không hữu ích · Trả lời 0

@ouah: Cái gì? Không, nó không có. consttrong thực tế, bị bỏ qua (bởi ngôn ngữ) đối với các đối số (cho dù chúng là con trỏ hay không là không liên quan; bạn đang nói về việc áp dụng constcho loại điểm bên dưới chứ không phải là loại đối số chức năng) trong các khai báo, bởi vì nó vô nghĩa. Nó chỉ hữu ích cho tính cục bộ consttrong định nghĩa hàm . Vậy làm thế nào nó có thể có bất kỳ ảnh hưởng nào đến API?

Hữu ích 1 · Không hữu ích · Trả lời 0

[C99: 6.7.5.3/15]: [..] (Trong việc xác định khả năng tương thích loại và loại hỗn hợp, mỗi tham số được khai báo bằng hàm hoặc loại mảng được lấy là có loại điều chỉnh và mỗi tham số được khai báo với loại đủ điều kiện được coi là phiên bản không đủ tiêu chuẩn của loại khai báo .) [..]

Hữu ích 1 · Không hữu ích · Trả lời 0

^ API (chức năng khai báo ) thậm chí không nhận được để thấy các consts. Áp dụng lại trong các định nghĩa chức năng là không liên quan.

Hữu ích 1 · Không hữu ích · Trả lời 0

Không chắc chắn tại sao Taylor sửa chữa trên con trỏ ở đó.

Hữu ích 0 · Không hữu ích · Trả lời 0

6
Phan Thanh Duy
6 năm trước

Đây là một ví dụ C đơn giản:

void PrintList(const struct List *l);
void SortList(struct List *l);
int  CmpList(const struct List *a, const struct List *b);
void AppendList(struct List *l, struct List *m);
void PushList(struct List *l, struct ListNode *n);
void PopList(struct List *l, struct ListNode *n);

Ở đây chúng ta có một tập hợp nhỏ các hàm làm việc với một số loại danh sách các nút. Đầu tiên, thậm chí không cần biết tên của các hàm, chúng ta có thể thấy ngay hàm nào thay đổi danh sách của chúng ta theo cách nào đó và hàm nào không. Các constchức năng, như trong các thư viện tiêu chuẩn, là các chức năng không thay đổi dữ liệu của bạn và sẽ không cho phép bạn thay đổi dữ liệu của mình với chúng. Trình biên dịch C cố gắng giữ cho độ constcủa các con trỏ được thực thi đối với dữ liệu bạn đang truyền đến các hàm. Vì vậy, trong trường hợp này, tôi có thể chắc chắn một cách hợp lý rằng so sánh hai danh sách không phải là chức năng xáo trộn chúng khi tôi thực hiện gỡ lỗi thời gian chạy, vì tôi đã tự bảo vệ mình trước các sửa đổi ngẫu nhiên đối với dữ liệu của mình. ;)

Hữu ích 6 Chia sẻ Viết bình luận 0
Không hữu ích

5
Tạ Tiến Đạt
6 năm trước

Trình biên dịch của bạn có thể thực hiện tối ưu hóa lớn, biết rằng một biến sẽ không bị thay đổi: thay vì lưu trữ nó trong bộ nhớ, nó được ghi trực tiếp vào opcode thực thi.

ví dụ: bạn có a và b, bạn muốn thêm chúng, bạn tạo a + b. Nếu bạn khai báo a là const và có giá trị 3, chương trình sẽ tạo 3 + b thay vào đó, điều này sẽ tiết kiệm bộ nhớ và quay vòng vì nó sẽ không cần lấy giá trị.

Vấn đề là trình biên dịch của bạn không thể biết trước nếu các biến không đổi hay không, tất nhiên nó có thể phân tích toàn bộ mã và kiểm tra xem bạn có sửa đổi các biến đó không, nhưng không chắc chắn 100%, vì mã trong tương lai cũng có thể sửa đổi nó.

Hữu ích 5 Chia sẻ Viết bình luận 0
Không hữu ích

4
Đỗ Trúc Quỳnh
6 năm trước

Từ khóa constrất hữu ích cho các nhóm và các dự án dài hạn. Tôi sẽ cung cấp cho bạn một vài ví dụ, những ví dụ này sẽ giải thích giá trị của consttừ khóa.

Hãy nói rằng bây giờ tôi đang tạo lib sẽ được sử dụng cho các dự án tiếp theo. Vì vậy, điều đó có nghĩa là mã được viết ngày hôm nay cần được tin cậy sau một vài năm, trong khoảng thời gian có thể xảy ra như vậy tôi sẽ quên biến nào không nên sửa đổi (đồng nghiệp thậm chí không biết cái gì có thể sửa đổi và cái gì không thể sửa đổi). Vì vậy, ví dụ ngắn này giải thích tại sao để sử dụng const.

Nói về ý kiến, khi thời hạn đến và có rất nhiều thứ vẫn không hoạt động bình luận về mọi chức năng sẽ chỉ là một sự lãng phí thời gian. Tuy nhiên, trong một số trường hợp, bình luận là bắt buộc, vì vấn đề đầu tiên (thời hạn) có thể không được đọc, bởi vì hầu hết chúng là vô ích nhưng những bình luận quan trọng cũng sẽ bị bỏ qua. Vì vậy, tốt hơn là sử dụng consttừ khóa gây ra lỗi biên dịch và chỉ cho bạn vấn đề sau đó viết và đọc nhiều bình luận.

Hữu ích 4 Chia sẻ Viết bình luận 0
Không hữu ích

2
Hoàng Quốc Bảo
6 năm trước

Đây là một câu hỏi khó vì IMO nó dựa trên niềm tin. Một trong những niềm tin là bạn có thể bảo vệ mã của bạn chống lại một số loại thay đổi chỉ thêm mã hơn. Tất nhiên, mã bổ sung đó được trình biên dịch sử dụng để kiểm tra mọi thứ đều ổn.

Tôi nghĩ rằng không phải lúc nào cũng đúng, bạn không thể bảo vệ mã của bạn chống lại chính mình hoặc nhóm phát triển của bạn chỉ cần thêm các từ khóa, trên thực tế có rất nhiều ngôn ngữ mà đừng có bất kỳ const, công cộng, tư nhân, bảo vệ, nội bộ, int, float, từ khóa kép và điều đó không có nghĩa là chúng không phải là ngôn ngữ tốt.

Điều tương tự cũng xảy ra với một số mẫu mã, tại sao mọi người lại lãng phí quá nhiều thời gian để thảo luận về Singletons!? Nếu bạn muốn chỉ có một thể hiện, điều duy nhất bạn phải làm là tạo ra chỉ một thể hiện, đó là tất cả. Cùng một suy nghĩ là ở khắp mọi nơi xung quanh, hãy xem các bài viết lập trình phòng thủ được xuất bản 10 năm trước, một lần nữa ý tưởng bảo vệ mã bằng mã.

Trong một số thời điểm, bạn phải quyết định nơi bạn muốn đặt trách nhiệm, trên tay các nhà phát triển hoặc trên các trình biên dịch. Tuy nhiên, cả trình biên dịch lẫn bất kỳ công cụ nào khác đều không thể lưu mã chống lại các nhà phát triển và vì lý do đó, rất nhiều từ khóa là vô giá trị hoặc chỉ là một cách để truyền đạt một cái gì đó cho các nhà phát triển khác.

Hữu ích 2 Chia sẻ Viết bình luận 0
Không hữu ích

2
Dương Bá Quân
6 năm trước

Hãy xem xét kịch bản mà bạn đang sử dụng cùng một hằng số nhiều lần trong toàn bộ dự án của bạn và bạn khó mã hóa nó ở mọi nơi. Bây giờ đột nhiên bạn được yêu cầu thay đổi giá trị của hằng số thành giá trị khác, vì vậy sẽ rất bận rộn để thay đổi tại tất cả các vị trí.

Vì vậy, tôi nghĩ rằng để làm cho mã của bạn dễ bảo trì hơn chắc chắn là một trong những lý do.

Hữu ích 2 Chia sẻ Viết bình luận 2
Không hữu ích

-1. Mặc dù câu trả lời của bạn là đúng, nhưng nó không liên quan nhiều đến câu hỏi. Câu hỏi là về lý do tại sao sử dụng công cụ sửa đổi const, câu trả lời là về lý do tại sao phải xác định ở một nơi duy nhất.

Hữu ích 3 · Không hữu ích · Trả lời 0

Tôi thừa nhận sai lầm của mình khi đưa câu hỏi theo cách khác. Xin lỗi, là lỗi của tôi!

Hữu ích 0 · Không hữu ích · Trả lời 0

1
Hoàng Yên Mai
6 năm trước

Các biến liên tục chỉ cho phép bạn viết mã dễ đọc hơn.

Việc sử dụng nhiều nhất cho consthầu hết các ngôn ngữ là cho phép chúng tôi sử dụng tên để chỉ các giá trị hằng, vì vậy bạn có thể nói với người khác, sử dụng ngôn ngữ lưu loát, tên này đề cập đến mà không cần truyền bá ý kiến ​​trong mã của bạn và tiết kiệm thời gian và công sức từ người đọc để biết loại tham số và đặc thù của các tham số. Tất nhiên, bạn cũng có lợi nếu giá trị không đổi của bạn được sử dụng lại trên mã của bạn. Chà, một mã như thế này có thể dễ đọc hơn:

processPages(LETTER_PAPER_WIDTH, LETTER_PAPER_HEIGHT);

...hơn cái này:

processPages(215.9, 279.4); // 8.5 x 11 Inches in millimeters for Letter Papers

Trong ví dụ trên, bạn cần hiểu từng tham số là gì, đơn vị của nó và loại để diễn giải các giá trị và bạn chưa cần xác thực nó với nhận xét, bởi vì một nhận xét dư thừa như thế này (những bình luận đó phát lại những gì được mã hóa) không phải là một nhận xét đáng tin cậy và hữu ích như vậy (là một nhận xét xấu theo Robert Martin trong Clean Code: http://goo.gl/5EyY ).

Hữu ích 1 Chia sẻ Viết bình luận 0
Không hữu ích

Trả lời của bạn

Xem trước nội dung