C ++: tham chiếu const, trước vs sau khi chỉ định kiểu


144

Sự khác biệt giữa các đối số trong:

int foo1(const Fred &arg) {
...
}

int foo2(Fred const &arg) {
...
}

? Tôi không thấy trường hợp này được nêu trong Câu hỏi thường gặp về parashift.



2
Đây có phải là một câu hỏi về phong cách? "const Fred" nghe có vẻ tốt trong tiếng Anh, nhưng "Fred const" có vẻ tốt hơn đối với tôi.
LatinSuD

1
Trên một lưu ý liên quan, có lý do nào người ta nên thích Fred const &arghơn Fred const& arg? Tôi thích cái sau tốt hơn bởi vì const&là một đơn vị có nghĩa là "constref" và tên argđược phân tách bằng một khoảng trống từ tất cả các chỉ định loại.
Frank

4
@dehmann: Nhưng không int const& refcó nghĩa là 'const ref' mà là 'ref to const'.
Cedric H.

Câu trả lời:


112

Không có sự khác biệt vì const được đọc từ phải sang trái đối với &, vì vậy cả hai đều đại diện cho một tham chiếu đến một thể hiện Fred bất biến.

Fred& constsẽ có nghĩa là tài liệu tham khảo là bất biến, là dư thừa ; khi giao dịch với const con trỏ cả hai Fred const*Fred* constcó giá trị nhưng khác nhau.

Đó là một vấn đề về phong cách, nhưng tôi thích sử dụng constnhư một hậu tố vì nó có thể được áp dụng nhất quán bao gồm các hàm thành viên const .


Sau đó, một điểm để làm std::is_const<const T&>::valuefalsegì?
vực thẳm.7 15/03/19

@ abyss.7 đó là một tài liệu tham khảo const T; các tài liệu tham khảo là đột biến.
Sean Fausett

125

Hành vi

Không có sự khác biệt về ngữ nghĩa giữa const T&T const&; ngôn ngữ coi chúng là cùng loại. (Điều tương tự áp dụng cho const T*T const*.)

Như một vấn đề của phong cách

Tuy nhiên, về vấn đề bạn nên thích theo phong cách, tôi sẽ không đồng ý với nhiều câu trả lời khác và thích const T&(và const T*):

  • const T&là phong cách được sử dụng trong cuốn sách Ngôn ngữ lập trình C ++ của Stroustrup .
  • const T& là phong cách được sử dụng trong chính tiêu chuẩn C ++.
  • const T*là phong cách được sử dụng trong cuốn sách Ngôn ngữ lập trình C của K & R.
  • const T* là phong cách được sử dụng trong tiêu chuẩn C.
  • Do các yếu tố trên, tôi nghĩ const T&/ const T*có quán tính nhiều hơn T const&/ T const*. const T&/ const T*theo kinh nghiệm dường như phổ biến hơn đối với tôi so với T const&/ T const*trong tất cả các mã C ++ và C mà tôi đã thấy. Tôi nghĩ rằng làm theo các thông lệ phổ biến là dễ đọc hơn so với việc tuân thủ các quy tắc phân tích cú pháp từ phải sang trái.
  • Với T const*, có vẻ như dễ dàng hơn để thất lạc các *như T* const(đặc biệt là nếu mọi người không như quen với nó). Ngược lại, const* Tkhông phải là cú pháp hợp pháp.

Điều gì về quy tắc phân tích cú pháp từ phải sang trái?

Về toàn bộ đối số phân tích cú pháp từ phải sang trái mà mọi người dường như thích sử dụng: như tôi đã đề cập trong một nhận xét cho một câu trả lời khác, cũng const T&đọc từ phải sang trái. Nó liên quan đến hằng số T. "T" và "hằng" mỗi có thể hoạt động như một tính từ hoặc một danh từ. (Ngoài ra, việc đọc T const*từ phải sang trái có thể mơ hồ vì nó có thể được hiểu không chính xác là "hằng số con trỏ đến T" thay vì "con trỏ đến hằng số T".)


3
+1, đã đồng ý. Khi đọc mã, dễ dàng phát hiện ra một const nếu dòng bắt đầu bằng const. Quy tắc phải trái thực sự chỉ cần thiết khi phân tích thủ công đặc biệt là khai báo kiểu lông. Tại sao không tối ưu hóa cho trường hợp phổ biến nhất? Ngoài ra, IMHO nếu bạn viết khai báo kiểu để bạn cần chạy thủ công một FSM trong đầu, bạn đang làm sai.
Andreas Magnusson

2
-1. Bất kể kết luận của bạn hợp lý đến mức nào và cá nhân tôi đồng ý với họ bao nhiêu, họ không trả lời trực tiếp câu hỏi . Điều này làm cho câu trả lời nhiều thứ hai cho một câu hỏi đơn giản xuất hiện như một câu nói ngớ ngẩn về một số máy móc lộn xộn dưới nước, không có kết luận, không có câu trả lời trực tiếp - không có gì. Bạn sẽ nhận được upvote của tôi khi bạn thêm một bản tóm tắt rõ ràng đơn giản ghi rõ " Không, không có sự khác biệt về ngữ nghĩa giữa cả hai cú pháp , nhưng có một số cân nhắc về phong cách như sau ...". Và chỉ sau đó tất cả những viên đạn.
ulidtko

1
IMO lý do const T&đọc tốt hơn, đó là: 1- Chúng tôi đọc mã từ trái sang phải. Và 2- Khi mô tả một khái niệm mới, chúng ta bắt đầu từ khái niệm tổng quát hơn đến cụ thể hơn. Đây,const từ khóa tổng quát hơn vì nó chia không gian biến thành hai loại, trong khi đó, bộ xác định loại chia nó thành nhiều loại.
pooya13

"Con trỏ tới" nên ở cùng nhau. Vì vậy, không có sự mơ hồ choT const*
Dexter

13

Mặc dù chúng là một và giống nhau, để duy trì tính nhất quán với quy tắc RIGHT-LEFT về phân tích cú pháp khai báo C và C ++, tốt hơn là viếtFred const &arg

Cũng tham khảo điều này để phát triển sự hiểu biết nhiều hơn về khai báo, vòng loại và khai báo.


1
Tôi thích hậu tố, bởi vì nó hoạt động tốt hơn với typedefviệc mở rộng. Ví dụ : typedef int* pointer;, const pointer không phải const int* , đó là int* const. Các hình thức hậu tố không khó xử.
Matthieu M.

4
IMO cũng const T&đọc từ phải sang trái; nó là một tham chiếu đến hằng số T. Tconstantmỗi có thể làm việc như một tính từ hoặc một danh từ.
jamesdlin

7

Cả hai công việc, và đây là lời giải thích từ người đàn ông đã viết nó.
Để báo cho anh ta:

Tại sao? Khi tôi phát minh ra "const" (ban đầu được đặt tên là "readonly" và có "writeonly" tương ứng), tôi đã cho phép nó đi trước hoặc sau loại vì tôi có thể làm như vậy mà không mơ hồ.




3

Tài liệu tham khảo không hoạt động giống như con trỏ: đối với con trỏ bạn có thể có 'consters con trỏ' (type * const p ) và 'con trỏ tới const' ( const type * phoặctype const * p ).

Nhưng bạn không có điều này để tham khảo: một tài liệu tham khảo sẽ luôn đề cập đến cùng một đối tượng; theo nghĩa đó, bạn có thể xem xét rằng 'tài liệu tham khảo' là 'tài liệu tham khảo' (giống như cách bạn có thể có 'con trỏ').

Do đó, một cái gì đó như 'type & const ref' là không hợp pháp. Bạn chỉ có thể có 'tham chiếu đến loại' (type &ref ) và 'tham chiếu đến loại không đổi' ( const type &refhoặctype const &ref ; cả hai đều tương đương chính xác).

Một điều cuối cùng: ngay cả khi const typetiếng Anh nghe đúng hơn, viết type constcho phép hiểu hệ thống hơn về khai báo "từ phải sang trái":int const & ref có thể được đọc có 'ref là một tham chiếu đến một hằng số int'. Hoặc ví dụ phức tạp hơn : int const * const & ref, ref là một tham chiếu đến một con trỏ không đổi đến một hằng số int.

Kết luận: trong câu hỏi của bạn, cả hai đều chính xác tương đương.

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.