Ngữ nghĩa C ++ của `static const` vs` const`


149

Trong C ++ cụ thể, sự khác biệt về ngữ nghĩa giữa các ví dụ là gì:

static const int x = 0 ;

const int x = 0 ;

cho cả hai staticnhư là một liên kết và một chỉ định lớp lưu trữ (tức là bên trong và bên ngoài một chức năng).


7
staticcó lẽ là từ khóa quá tải nhất trong C ++. Ý nghĩa mã của bạn rất khác nhau tùy thuộc vào việc nó ở phạm vi không gian tên, ở phạm vi lớp hay ở phạm vi chức năng. Bạn có thể muốn làm rõ điều đó.
sbi

1
@sbi: Mình nghĩ mình đã làm rồi. Phạm vi chức năng (trong đó nó là một công cụ xác định lớp lưu trữ) và phạm vi tệp (trong đó nó là một công cụ xác định liên kết). Các thành viên trong lớp và các biến trong phạm vi không gian tên đặc biệt không liên quan đến tôi đối với câu hỏi này, mặc dù nếu bất cứ ai cảm thấy có sự khác biệt thú vị, hãy thoải mái đề cập đến điều đó.
Clifford

@Clifford: Tôi xin lỗi tôi đã bỏ qua những từ cuối cùng. Tuy nhiên, điều này đã tiết lộ một sự hiểu lầm từ phía bạn: Trong C ++, phạm vi tệp phạm vi không gian tên. Nếu bạn khai báo bất cứ điều gì bên ngoài bất kỳ không gian tên nào, nó sẽ chỉ thuộc về không gian tên toàn cầu (và có thể truy cập thông qua một tiền tố ::không có định danh ở phía trước). Tôi không nhận thấy bất kỳ sự khác biệt có ý nghĩa nào giữa không gian tên toàn cầu và bất kỳ không gian tên nào được lồng trong nó. Chắc chắn không có bất kỳ liên quan đến staticcác đối tượng.
sbi

1
liên kết khác với khả năng hiển thị , bằng cách sử dụng chúng thay thế cho nhau, bạn sẽ nhầm lẫn giữa những người bạn nói chuyện và có lẽ cả chính bạn.
Ben Voigt

1
@Ben, @sbi: Tôi không có ý định đề xuất rằng phạm vi tệpliên kết tĩnh là như nhau, chỉ đơn thuần là liên kết tĩnh ngụ ý phạm vi tệp. Theo nghĩa này, phạm vi (hoặc khả năng hiển thị) là một thuộc tính của liên kết tĩnh và bên ngoài, không phải là từ đồng nghĩa cho một trong hai. Tôi cảm thấy rằng câu hỏi ban đầu vẫn rõ ràng và được hình thành rõ ràng, và rằng chúng tôi chỉ đang thảo luận về các ý kiến ​​được đưa ra để đáp lại nhận xét có phần hạ thấp của sbi. Chúng tôi đang thảo luận về ngữ nghĩa không chính xác của tiếng Anh ở đây hơn là sự hiểu biết của tôi, vì vậy tôi nghĩ rằng chúng ta có thể dừng lại.
Clifford

Câu trả lời:


128

Ở phạm vi tập tin, không có sự khác biệt trong C ++. constlàm cho liên kết nội bộ trở thành mặc định và tất cả các biến toàn cục có thời gian tồn tại tĩnh. Nhưng biến thể đầu tiên có hành vi tương tự trong C, vì vậy đó có thể là một lý do tốt để sử dụng nó.

Trong một chức năng, phiên bản thứ hai có thể được tính toán từ các tham số. Trong C hoặc C ++, nó không phải là hằng số thời gian biên dịch như một số ngôn ngữ khác yêu cầu.

Trong một lớp, về cơ bản giống như đối với các hàm. Một constgiá trị cá thể có thể được tính toán trong danh sách ctor-khởi tạo . A static constđược đặt trong quá trình khởi động và không thay đổi trong phần còn lại của chương trình. (Lưu ý: mã cho staticcác thành viên trông hơi khác một chút vì khai báo và khởi tạo được tách riêng.)

Hãy nhớ rằng, trong C ++, constcó nghĩa là chỉ đọc , không phải là hằng số . Nếu bạn có một con trỏ trỏ đến constthì các phần khác của chương trình có thể thay đổi giá trị trong khi bạn không tìm kiếm. Nếu biến được định nghĩa bằng const, thì không ai có thể thay đổi nó sau khi khởi tạo nhưng việc khởi tạo vẫn có thể phức tạp tùy ý.


1
Có bất cứ điều gì được gọi là phạm vi tập tin? Tôi chỉ kiểm tra $ 3,3 và tôi nghĩ gần nhất là 'phạm vi không gian tên'. Là sự hiểu biết của tôi phải không? Phạm vi tệp tiêu chuẩn C ++ 03 chỉ đề cập trong các Phụ lục
Chubsdad

2
Tôi muốn đề xuất rằng phạm vi tệp là một vật phẩm của trình liên kết chứ không phải trình biên dịch, vì vậy có thể không được chú ý nhiều trong tiêu chuẩn ngôn ngữ. Nghiêm túc đó có lẽ là "phạm vi đơn vị biên dịch".
Clifford

8
+1 cho cụm từ "const có nghĩa là chỉ đọc, không phải là hằng số", nghĩa là "Trình biên dịch, nếu bạn thấy ai đó đang cố gắng sửa đổi điều const này, hãy sủa thật to." Đây là lý do một cái gì đó có thể được const & dễ bay hơi cùng một lúc.
Dan

5
Đó là "Trình biên dịch, nếu bạn thấy tôi cố gắng sửa đổi điều này (hoặc cho phép người khác làm như vậy)", sủa rất to. Trong hầu hết bối cảnh, constáp dụng cho chế độ xem biến và không phải chính biến đó, người khác có thể có constchế độ xem không cùng biến và trình biên dịch sẽ khá im lặng khi họ sửa đổi.
Ben Voigt

1
@Ben: Để rõ ràng, C ++ 0x không loại bỏ việc sử dụng cụ thể đó const, nhưng cái mới constexprcó thể được sử dụng thay thế (và trong các tình huống khác nữa). Trên thực tế, tiêu chuẩn C ++ 0x cũng mở rộng khả năng sử dụng consttrong kịch bản đó thành "các loại chữ" không tách rời. Tôi nghĩ rằng tôi thích sử dụng constexprcho những trường hợp đó, vì dù sao bạn cũng sẽ phá vỡ tính tương thích ngược với trình biên dịch trước C ++ 0x.
Michael Burr

4

Dự thảo tiêu chuẩn C ++ 17 về constngụ ý staticở phạm vi tệp

Đây là trích dẫn cho những gì đã được đề cập tại: https://stackoverflow.com/a/3709257/895245

Dự thảo tiêu chuẩn C ++ 17 n4659 6.5 "Chương trình và liên kết":

3 Tên có phạm vi không gian tên (6.3.6) có liên kết bên trong nếu đó là tên của

  • (3.1) - một mẫu biến, hàm hoặc hàm được khai báo tĩnh; hoặc là,
  • (3.2) - một biến không nội tuyến của loại không đủ điều kiện const không dễ bay hơi, không được khai báo rõ ràng bên ngoài và trước đó được tuyên bố là có liên kết bên ngoài; hoặc là
  • (3.3) - một thành viên dữ liệu của một liên minh ẩn danh.

Phụ lục C (thông tin) Tính tương thích, C.1.2 Khoản 6: "các khái niệm cơ bản" đưa ra lý do tại sao điều này được thay đổi từ C:

6.5 [cũng 10.1.7]

Thay đổi: Tên của phạm vi tệp được khai báo rõ ràng const và không được khai báo bên ngoài rõ ràng, có liên kết bên trong, trong khi ở C, nó sẽ có liên kết ngoài.

Đặt vấn đề: Vì các đối tượng const có thể được sử dụng làm giá trị trong quá trình dịch trong C ++, tính năng này thúc giục các lập trình viên cung cấp một trình khởi tạo rõ ràng cho từng đối tượng const. Tính năng này cho phép người dùng đặt các đối tượng const trong các tệp nguồn được bao gồm trong nhiều đơn vị dịch thuật.

Ảnh hưởng đến tính năng gốc: Thay đổi thành ngữ nghĩa của tính năng được xác định rõ.

Khó chuyển đổi: Chuyển đổi ngữ nghĩa.

Cách sử dụng rộng rãi: Ít khi.

Xem thêm: Tại sao const ngụ ý liên kết nội bộ trong C ++, khi nó không có trong C?

Thay vào đó, những gì bạn có thể muốn làm

Giải thích chi tiết tại: 'const static' có nghĩa là gì trong C và C ++?

  • pre C ++ 17: externtrong tiêu đề, định nghĩa trong tệp cpp
  • bài C ++ 17: biến nội tuyến trên tiêu đề

Cảm ơn, mặc dù tôi không nghĩ rằng đây là cơ hội trong C ++ 17 so với C ++ 98, và câu hỏi đã được hỏi vào năm 2010. Hơn nữa, câu trả lời của bạn chỉ liên quan đến tĩnh như một công cụ xác định liên kết (ở phạm vi không gian tên) và câu hỏi được hỏi cụ thể về ngữ nghĩa trong các bối cảnh khác nhau.
Clifford

@Clifford có, chắc chắn cũ hơn C ++ 17, chỉ lười đọc tất cả các tiêu chuẩn ;-) Sẽ làm rõ phần phạm vi tệp.
Ciro Santilli 郝海东 冠状 病 事件
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.