Trong C / C ++, tôi có nên sử dụng 'const' trong các tham số và biến cục bộ khi có thể không?


13

Câu hỏi này được lấy cảm hứng từ một câu hỏi về finaljava .

Trong C / C ++, tôi có nên sử dụng constbất cứ khi nào có thể?

Tôi biết đã có một câu hỏi liên quan về việc sử dụng consttrong các tham số . Thật không may câu hỏi đó và câu trả lời của nó không trả lời đầy đủ câu hỏi của tôi, bởi vì đó chỉ là về các tham số chức năng, nhưng tôi cũng muốn biết về các trường hợp khác (ví dụ: biến cục bộ).

Ngoài ra, hầu hết tất cả các câu trả lời cho câu hỏi đó đều nói rằng chúng ta nên sử dụng constvì nó chứa thông tin hữu ích về khả năng truy cập của các biến. Nhưng điều này dường như mâu thuẫn với một câu trả lời về việc sử dụng cuối cùng trong Java , trạng thái finalcó thể là thừa nếu nó không chứa thông tin bổ sung và vì vậy nó nên được bỏ qua để giữ cho mã ngắn và sạch.

Vì vậy, tôi nên sử dụng constbất cứ khi nào có thể? Nếu vậy, tại sao lời khuyên cho constC ++ lại khác với lời khuyên cho finalJava?

Câu trả lời:


18

Trước hết, vì bạn đã tham chiếu Java final, đó là một con thú hoàn toàn khác const. Cuối cùng có nghĩa là tài liệu tham khảo không thể thay đổi, nhưng không nói gì về tính đột biến. Const đi xa hơn bằng cách nói "một tham chiếu const không thể thay đổi", đó là một đảm bảo mạnh mẽ hơn nhiều. Để làm điều này trong Java, trạng thái bên trong phải là cuối cùng và được xác định tại thời điểm xây dựng. Const dễ sử dụng hơn rất nhiều và một đối tượng hiện có có thể được "quảng bá" thành một tham chiếu const.

Có, bạn nên sử dụng const bất cứ khi nào có thể. Nó làm cho một hợp đồng rằng mã của bạn sẽ không thay đổi một cái gì đó. Hãy nhớ rằng, một biến không const có thể được truyền vào một hàm chấp nhận tham số const. Bạn luôn có thể thêm const, nhưng không lấy nó đi (không phải không có const const, đó là một ý tưởng thực sự tồi tệ).

Đôi khi tính chính xác có thể tẻ nhạt, nhưng nó giúp đảm bảo tính bất biến. Điều này rất quan trọng trong mã đa luồng trong đó các luồng chia sẻ các đối tượng. Nó làm cho một số tác vụ nhất định hiệu quả hơn: thay vì sao chép trạng thái, chỉ cần sử dụng lại cùng một đối tượng bất biến. Các thư viện có thể chấp nhận các tham số const để đảm bảo cho lập trình viên rằng không, đối tượng của bạn sẽ không thay đổi theo cách không thể đoán trước trong lỗ đen đó là can đảm của thư viện.


1
Bỏ phiếu vì bạn giải thích điều đó finalconstkhông có cùng một sự đảm bảo.
Cửa Bill

2
Constness là về khả năng ghi, không phải về khả năng biến đổi.
Basilevs

@Basilevs điều gì xảy ra nếu bạn viết cho một đối tượng? Nó đột biến. Làm thế nào để bạn đột biến một đối tượng? Viết cho nó

4
Điều gì xảy ra nếu bạn viết cho một tài liệu tham khảo const? Một lỗi thời gian biên dịch. Điều gì xảy ra nếu bạn viết cho đối tượng được tham chiếu ở đâu đó bằng tham chiếu const qua một tham chiếu không phải const khác? Nó đột biến. Đối tượng bất biến không thể biến đổi, do đó const refcece không nhất thiết phải tham chiếu đối tượng bất biến.
Basilevs

@Basilevs quan sát của bạn chỉ áp dụng với const refs. Nếu một đối tượng tự nó được khai báo const (không chỉ là tham chiếu) thì nó ít nhiều không thay đổi (trừ khi có ai đó bỏ đi một cách bất chính).
Matthew James Briggs

4

Cá nhân, consttôi mất rất ít thời gian để viết và rất ít thời gian để đọc, thường là ít hơn nhiều so với việc kiểm tra xem có bất kỳ mã nào làm biến đổi biến không và nó có thực sự ngăn tôi viết lỗi không (có ai từng tăng vòng lặp cuối của họ một cách tình cờ không? Vân vân)

Tôi cũng thấy rằng việc nghiêm ngặt về việc sử dụng const hướng dẫn tôi hướng tới mã tốt hơn theo những cách khác, như tạo các hàm trợ giúp để thực hiện khởi tạo không tầm thường.


4

Tôi sẽ không đồng ý với các áp phích khác và khuyên bạn không nên sử dụng cấp cao nhất constcho các biến và tham số cục bộ. (Các tham chiếu và con trỏ tới const, nghĩa const T&là khác nhau, và bạn nên sử dụng chúng cho chính xác mọi lúc khi nó phù hợp.)

Những lợi thế của cấp cao nhất constlà:

  • Làm cho nó rõ ràng rằng các biến cục bộ không có nghĩa là bị đột biến.
  • Đưa ra một lỗi biên dịch nếu bạn vô tình cố gắng làm biến đổi chúng.

Những nhược điểm là:

  • Thị giác lộn xộn.
  • Không thể được sử dụng trên các biến "pseudo-const", tức là các biến được khởi tạo theo một cách nào đó phức tạp hơn so với xây dựng trực tiếp, nhưng không được sửa đổi sau, ví dụ: sử dụng getline:

    std::string line; // cannot be const
    std::getline(std::cin, line);
    // line should be const from here on out
  • Ngăn chặn tối ưu hóa di chuyển ra khỏi chức năng gọi và trả về:

    std::string f1();
    std::string f2(std::string s);
    std::string f3() {
      const std::string s = f1(); // s is not meant to be modified
      // but I still want the move optimization here:
      const std::string result = f2(std::move(s)); // this doesn't move
      // and I want the compiler to move out here:
      return result; // this will probably RVO, but if not, the move
                     // constructor will not be used due to the const
    }

Tôi đã làm việc trên một cơ sở mã nơi mà địa phương constđược sử dụng rất nhiều và tôi thấy nó không hữu ích chút nào, nhưng nó chứa đầy mã với sự bi quan tinh tế như trên. Cá nhân tôi thích áp dụng chính sách chung là sửa đổi các biến càng hiếm càng tốt và làm cho các hàm đủ nhỏ để việc sử dụng biến là rõ ràng và ngay cả khi nó được sửa đổi, độ phức tạp của hàm đủ thấp để biến nó thành không -vấn đề.


2
Quan điểm của bạn về việc chuyển từ đang cho thấy bạn không sử dụng cục bộ theo cách riêng, vì bạn (có ý định) sửa đổi nó bằng cách di chuyển
Caleth

1
@Caleth Không, đó là điểm chính. Tôi không có ý định sửa đổi nó. Tôi chỉ muốn vượt qua giá trị, hoặc trả lại nó, và tôi muốn nó có hiệu quả. Về mặt khái niệm, sửa đổi chỉ là một tối ưu hóa, không có nghĩa là có thể quan sát được (vì các biến không được sử dụng sau đó). Thực tế, vâng, có một sửa đổi, vì C ++ không có động thái phá hoại thực sự (như Rust có). Đó chính xác là lý do tại sao tôi không muốn constở địa phương: bởi vì nó ngăn chặn sửa đổi kỹ thuật, không chỉ là sửa đổi khái niệm.
Sebastian Redl

2
Bạn không muốn sửa đổi giá trị , nhưng bạn muốn sửa đổi biến . Thay vào đó, bạn có thể sử dụng const & thay vào đó và sửa đổi cả
Caleth

2

Các consttừ khóa nên được sử dụng cho các biến địa phương, giống như thông số. Nó hữu ích vì:

  • Dễ đọc mã hơn. Khi ai đó đọc khai báo biến, cô ấy biết nó sẽ không thay đổi. Một điều ít phải lo lắng trong khi đọc mã của bạn.
  • Ngăn chặn bạn vô tình sửa đổi biến
  • Không có hình phạt thời gian chạy, tất cả mọi thứ được kiểm tra tĩnh. Nó giống như một bữa trưa miễn phí, constchỉ mất một giây để viết, vì vậy nó không phải là vấn đề lớn.
  • Luôn luôn là một ý tưởng tốt để tạo các biến / tham số của bạn trong các ứng dụng đa luồng của bạn. Ngay cả ứng dụng của bạn không đa luồng, nó vẫn là một thói quen tốt.
  • Bạn tạo cơ hội cho trình biên dịch C ++ của bạn để tối ưu hóa mã của bạn.

Lưu ý rằng không có câu trả lời đúng / sai ở đây. Trong liên kết của bạn, người trả lời có nhiều câu hỏi nhất finalkhông nên sử dụng cục bộ. Tuy nhiên, người trả lời tiếp theo rất khuyến khích nó.

Nếu chức năng của bạn đơn giảntầm thường , bạn không nên thêm constvì mọi người đều hiểu ý định của bạn. Tuy nhiên, nếu logic trong chức năng của bạn là không tầm thường, bạn nên sử dụng từ khóa. Hãy nhớ rằng, có rất ít để mất.

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.