Làm thế nào bạn trở thành một chuyển đổi chính xác const? [đóng cửa]


25

Sau 15 năm C ++, tôi vẫn chưa học được cách sử dụng const. Tôi hiểu nó được sử dụng, nhưng tôi chưa bao giờ thực sự ở trong tình huống mà const const đúng sẽ tránh được vấn đề tôi gặp phải.

Vì vậy, làm thế nào bạn đến với tình yêu lợi ích của consts?


3
Tôi nghĩ rằng tính chính xác của const không phải là chính xác hơn là một công cụ để giải quyết vấn đề như nếu constrcut hoặc toán tử sizeof.
huyền thoại2k

9
"Lý do const hoạt động trong C ++ là vì bạn có thể bỏ nó đi. Nếu bạn không thể bỏ nó đi, thì thế giới của bạn sẽ bị hút đi." - Anders Hejlsberg
Mason Wheeler

1
const cũng là một công cụ sửa đổi loại C và đã có từ tiêu chuẩn ANSI C đầu tiên.
Huperniketes

Bị hư hỏng bởi Java / C #, tôi thuộc tuýp người hoang tưởng, thích để lại khẳng định bất kỳ cơ hội nào tôi có được. Những gì có thể đi sai sẽ đi sai. Nếu có thời gian biên dịch hoặc hỗ trợ thời gian chạy, thì hãy đếm tôi! Tôi đã trở thành một người chuyển đổi ngay khi tôi nghe về nó 3-4 lần và theo một phần của liên kết này (đủ để thấy cú pháp, tôi không cần phải đọc về lý do tại sao): ability.com/Cpp/const.html Chỉ vì một cái gì đó chưa xuất hiện trên khuôn mặt của tôi ... nó cần ít nỗ lực để được chính xác, và nó không bị tổn thương. Kiểm tra suy nghĩ của Joel: joelonsoftware.com/articles/Wrong.html
Công việc

Câu trả lời:


28

Vâng, tôi đã không bị thuyết phục cho đến khi tôi cố gắng nắm lấy triết lý.

Trước tiên tôi bắt đầu bằng cách đưa constvào các thành viên thực sự chỉ đọc của các thành viên lớp cơ bản nhất và các đối số chức năng thành viên.

Từ đó, tôi không thể biên dịch được nữa. Sau đó, tôi đã kiên trì sử dụng mã bằng các lớp cơ bản đó, xem các constbổ sung trước đó có thực sự hợp pháp so với việc sử dụng chúng được thực hiện không. Nó giúp tôi sửa một số lỗi trên đường khi tôi thêm hằng số vào các phần khác của mã.

Nó lây nhiễm. Hầu hết các mã thậm chí còn có nhiều hằng số hơn và tôi thấy việc gỡ lỗi nó dễ dàng hơn bởi vì nó làm cho bạn tự tin rằng trình biên dịch sẽ dừng bạn nếu bạn bắt đầu sửa đổi một cái gì đó bạn không nên.

Khi tôi chạy ứng dụng, nó sẽ nhanh hơn (phải thay đổi một số thuật toán mà tôi phát hiện ra không phù hợp với công việc), với rất ít lỗi và dễ hiểu hơn khi đọc mã.

Tôi đã bị thuyết phục.

Bây giờ, tôi nghĩ rằng nó thậm chí còn tốt hơn khi bạn đang sử dụng rất nhiều xác nhận ngoài việc xác định bởi vì nó khiến bạn cảm thấy tự tin khi bạn phải viết mã mới hoặc sửa đổi mã hiện tại. Bạn biết trình biên dịch sẽ dừng bạn nếu cần thiết. Nó cho phép bạn quên đi việc phải kiểm tra mọi thứ bạn không nên sửa đổi và sau đó bạn có nhiều thời gian suy nghĩ hơn để suy nghĩ cụ thể hơn về kinh doanh hoặc tư duy kiến ​​trúc.


8
+1 cho truyền nhiễm, về cơ bản có nghĩa là bạn phải trở thành một người chuyển đổi const hoặc hoàn toàn tránh nó.
Martin Wickman

Bạn cũng cần không dựa vào lib mà không làm đúng. Cách tiếp cận của bạn không hoạt động khi điều đó có nghĩa là bạn không thể gọi bất kỳ chức năng gui nào vì chúng không phải là - hoặc bạn cần loại bỏ nó trong mỗi cuộc gọi gui.
Martin Beckett

4
+1 cho "tìm thấy dễ gỡ lỗi hơn", tôi sử dụng constngay cả cho biến cục bộ mà tôi biết tôi sẽ không cần thay đổi, theo cách này khi đọc mã tôi có thể lướt qua a ifhoặc a forhoặc whatelse: biến của tôi là hằng số, tôi biết nó sẽ không thay đổi! Tôi không thể quan tâm ít hơn về việc tối ưu hóa, nhưng tôi có bộ não hạn chế và một vài mức độ thụt lề + độ chính xác giúp ích rất nhiều!
Matthieu M.

@MatthieuM.: Bạn đã bao giờ cân nhắc chuyển sang Haskell chưa? ;-)
Giorgio

@Giorgio: Tôi đã khám phá nó, thậm chí đã đi xa đến mức mua "Real World Haskell". Thành thật mà nói, tôi không vui mừng với sự lười biếng theo mặc định và nhiều nhà khai thác tiền điện tử đã mọc lên.
Matthieu M.

15

Tôi chưa bao giờ là người đề xuất lập trình hướng đối tượng, và nếu có gì tôi đã phát triển ít hơn thì tôi càng học nhiều hơn về lập trình nói chung. Khi tôi nghiên cứu các mô hình lập trình khác nhau, tôi nhận ra rằng tính bất biến là một trong những khái niệm trung tâm của thiết kế chương trình, ảnh hưởng đến phần mềm được viết theo bất kỳ triết lý nào . Nó cực kỳ quan trọng trong lập trình chức năng, với ý nghĩa tối ưu hóa và đồng thời trên các đảm bảo an toàn đơn giản.

Về cơ bản, mọi thứ có thể là bất biến có lẽ nên , trừ khi bạn có lý do chính đáng cho trạng thái đột biến. Theo kinh nghiệm của tôi, viết chương trình bằng bất kỳ ngôn ngữ nào để theo đuổi mục tiêu này dẫn đến mã an toàn hơn, tốt hơn . Bạn không có gì để mất bằng cách sử dụng constnơi mà tính bất biến áp dụng của Haiti là miễn phí!

(Ngẫu nhiên, tôi đã đùa giỡn với ý tưởng tạo ra một ngã ba của GCC cho một phương ngữ C ++, trong đó tất cả các loại là consttrừ khi rõ ràng có trình độ như mutable. Nếu có sự hỗ trợ cho một điều như vậy, tôi sẽ hoàn toàn cam kết duy trì và sử dụng nó.)


Từ quan điểm OO, tính bất biến thực thi đóng gói bằng cách ngăn chặn truy cập ghi không hạn chế. Nó làm giảm sự ghép nối giữa các lớp vì các đối tượng bất biến phải quản lý hoàn toàn trạng thái của chính chúng và do đó hoạt động như các giá trị thông thường. Tính chính xác của Const làm giảm đáng kể quá trình chứng minh tính đúng đắn của chương trình, đặc biệt là trong bối cảnh lập trình đồng thời. Với tham chiếu C ++ và ngữ nghĩa tham chiếu giá trị C ++ 0x, bạn có thể sử dụng các đối tượng bất biến mà không phải lo lắng về chi phí sao chép chúng ở mọi nơi. Hơn nữa, trình biên dịch có thể hoạt động một số phép thuật tối ưu hóa khá tuyệt vời nếu bạn làm việc với các đối tượng chủ yếu là bất biến.

Tôi biết nó rất hấp dẫn để gõ constở mọi nơi, nhưng bạn nhanh chóng quen với nó và lợi ích trở nên rõ ràng theo thời gian về độ tin cậy và khả năng bảo trì. Tôi không phải là một nhà văn xuất sắc và dường như là một nhiệm vụ khó khăn đã được chứng minh để tạo ra một trường hợp cho nó, nhưng tôi biết rằng sự đúng đắn đã giúp tôi rất nhiều khi là một nhà phát triển khi thiết kế và thực hiện các chương trình, và tôi nghĩ kinh nghiệm là giáo viên tốt nhất trong vấn đề này.


2
Về cơ bản, bạn chỉ nói rằng const đúng là một điều tốt. Bạn nói rằng nó "dẫn đến mã an toàn hơn, tốt hơn". Bạn có thể nói tại sao không?
David Reis

Tôi hoàn toàn ở trong trại bất biến, ngôn ngữ yêu thích của tôi là Erlang. Nhưng tôi sẽ lập luận rằng tính bất biến thông qua const trong C ++ không thực sự miễn phí. Có những nhược điểm như mã ít đọc, các phiên bản const và non const của cùng một phương thức, hoặc bỏ const const vì "không có lựa chọn nào khác".
Grok

1
Tôi khuyên bạn không chỉ sử dụng mutable, vì nó có ý nghĩa rõ ràng về mặt chính xác. Điều đó có nghĩa là đối tượng dữ liệu này có thể thay đổi theo cách không ảnh hưởng đến hành vi của đối tượng và cho phép những thứ như bộ đệm trả lời. Tạo một từ khóa khác.
David Thornley

2
@David Thornley: Vì sự nhất quán, mutablelà lựa chọn hợp lý. void alter(mutable Point&)có ý nghĩa, cũng như mutable int foođối với một biến cục bộ và cả hai điều này không mâu thuẫn với ngôn ngữ hiện có hoặc việc sử dụng hiện có mutable. Ngoài ra, Object mutable* mutabletrông đủ đáng sợ để trở thành một cảnh báo về việc nó cần thiết hay chính xác.
Jon Purdy

Nếu bạn đã từng làm ngã ba, hãy cân nhắc đến việc đi với CLang - nên sẽ bớt đau hơn.
gf

6

Ưu điểm của tính chính xác là nó áp đặt một kỷ luật đối với chương trình và giúp dễ dàng suy luận về các phần của chương trình.

Kỷ luật là bạn cần biết nơi nào đó có thể được thay đổi. Ưu điểm tương ứng là dễ dàng hơn để xem một đoạn mã làm gì khi bạn có thể biết điều gì có thể thay đổi trạng thái.


1
"Các chương trình phải được viết để mọi người đọc và chỉ tình cờ cho các máy thực thi." - Abelson & Sussman, SICP
Brandon DuRette

4

const đúng nhấn mạnh sự đúng đắn của thiết kế mà tôi đối xử với gần một vấn đề tương tự mà không được sử dụng khai thác lộ thiên; vì vậy không sử dụng cast và được const chính xác, sử dụng tối thiểu khả năng biến đổi - tất cả đều là con trỏ để đo mức độ tốt của thiết kế nhưng không phải là công cụ thực tế để giải quyết vấn đề tổng thể trong tay.

Tái bút: Tôi đã hoàn toàn bị thuyết phục constkhi tôi hiểu được tính đúng đắn của việc sử dụng nó;)



2

Tôi thấy hai lý do chính để viết mã const-true. Một là trình biên dịch là bạn của bạn và bằng cách sử dụng const bạn để nó cảnh báo bạn về các lỗi tiềm ẩn. Lý do thứ hai là tính chính xác làm cho mã dễ đọc hơn. Ví dụ, bạn luôn biết đối số hàm nào là đầu vào và đầu ra nào. Bạn cũng biết chức năng thành viên nào sửa đổi đối tượng và cái nào không. Bạn biết những điều này ngay lập tức mà không cần phải đọc qua mã. Điều này, tất nhiên, giả sử sử dụng rất hợp lý const_cast.


2

Tôi là một người chuyển đổi ngay khi tôi biết điều đó là có thể. Nó có ý nghĩa với tôi từ quan điểm 'phong cách lập trình tốt'. Có nhiều lý do giải thích tại sao nên thực hành đúng:

  • Dễ đọc và hiểu. Nếu tôi đang đọc mã của người khác và một hàm lấy tham chiếu const làm tham số thì tôi biết rằng tham số đó chỉ có nghĩa là được sử dụng làm biến chỉ đọc. Đây là một chiến thắng lớn đặc biệt là nếu mã là môi trường đa luồng.
  • Trình biên dịch có thể sử dụng vòng loại const để hỗ trợ vượt qua tối ưu hóa của nó.
  • Nói rằng tôi có một đối tượng của lớp A trong tình huống mà tôi không muốn nó thay đổi. Sau đó, các hàm thành viên duy nhất có thể được gọi cho đối tượng đó là các hàm const.

2

Để tóm tắt hai điểm đã được đề cập trong các câu trả lời khác và thêm một điểm mới:

  • consttài liệu mã cho người dùng API của bạn. Nó tạo thành một hợp đồng giữa một chức năng và người gọi của nó, rằng chức năng đó sẽ không sửa đổi các tham số của nó. (Xin lưu ý rằng const_castkhông cho phép một hàm thay đổi tham số của nó, nó cho phép chuyển tham số đó sang các hàm khác không sửa đổi các tham số của chúng mà quên constchú thích.) Nó cũng hữu ích trong các hàm / loop / etc cùng một cách như một vòng lặp bất biến.

  • consttài liệu ý định của bạn để trình biên dịch. Tìm lỗi trong thời gian biên dịch luôn tốt hơn là chờ đoạn mã đó chạy.

  • constlà cần thiết cho loại đa hình an toàn. Con trỏ (trong tất cả các dạng của chúng, không chỉ là con trỏ thô) chỉ là biến số nếu chúng là const(Lưu ý: không giống như "con trỏ tới const"). Hiệp phương sai yêu cầu giao diện chỉ đọc và chống chỉ định yêu cầu giao diện chỉ ghi.

Thứ hai trong số này tôi học đầu tiên. Tôi đã bắt đầu constchỉ với mục tiêu của các tham số con trỏ và tham chiếu, cho đến khi tôi bắt đầu thấy lợi ích của việc bắt lỗi trước đó và bắt đầu sử dụng nó trên các địa phương, v.v.

Sau đó, tôi đã học được rằng hầu hết #definecác s có thể được thay thế (trong C ++) bằng các hằng số toàn cầu, với các lợi ích bổ sung của an toàn kiểu. Vì vậy, tôi đã sử dụng nó ở đó quá.

Cuối cùng tôi đã tham gia một lớp học về các hệ thống loại và phép tính lambda, và học được rằng constcác constloại không khác nhau về cơ bản (vì chúng hỗ trợ các hoạt động khác nhau), và từ đó tôi thậm chí chưa bao giờ xem xét việc viết mã C ++ mà không sử dụng nhiều const.


1

Đây là 5 xu của tôi về những gì tôi chưa thấy người khác đề cập. Khi chuyển qua các biến bạn không muốn chuyển theo giá trị, trừ khi bạn thực sự cần, để tránh các cấu trúc bổ sung và phá hủy và bản sao. Vì vậy, trừ khi bạn thực sự phải vượt qua giá trị, sử dụng tài liệu tham khảo ở mọi nơi, ngay cả khi bạn không có ý định thay đổi giá trị được thông qua là một sự gia tăng hiệu suất đáng kể. Vì lý do này, khi bạn có các hàm lấy tham chiếu của tất cả các đối số của nó, bạn cần cho người gọi biết chức năng nào sẽ không được sửa đổi.

Nguyên tắc tương tự, nhưng tôi chỉ muốn thêm một lý do thực tế của việc sử dụng const.

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.