Tại sao std :: ssize () được giới thiệu trong C ++ 20?


99

C ++ 20 đã giới thiệu std::ssize()hàm miễn phí như sau:

template <class C>
    constexpr auto ssize(const C& c)
        -> std::common_type_t<std::ptrdiff_t,
                              std::make_signed_t<decltype(c.size())>>;

Một triển khai khả thi dường như sử dụng static_cast, để chuyển đổi giá trị trả về của size()hàm thành viên của cl ass C thành đối tác có dấu của nó.

size()hàm thành viên của C luôn trả về các giá trị không âm, tại sao mọi người lại muốn lưu trữ chúng trong các biến có dấu? Trong trường hợp một người thực sự muốn, đó là một vấn đề đơn giản static_cast.

Tại sao lại được std::ssize()giới thiệu trong C ++ 20?


4
@ Jarod42 Nó không phải là triển khai được xác định thay vì không xác định? (tràn đã ký là không xác định. nhưng chuyển đổi có ký là việc triển khai được xác định)
phön

8
Giá như họ thêm ssizeoftoán tử là tốt.
geza

3
Điều này có thể hơi liên quan: stackoverflow.com/questions/30395205/…
Marco13

10
@ JohnZ.Li Có nguy cơ nghe có vẻ quá viển vông: Tôi nghĩ rằng toàn bộ hệ thống kiểu của C ++ liên quan đến các kiểu số nguyên đã bị hỏng. Chắc chắn, người ta có thể tranh luận rằng một số điều kỳ quặc (chẳng hạn như không biết a charcó bao nhiêu bit ) được thừa hưởng từ C và ít nhất là phần nào được giảm bớt (u)intX_t, nhưng nó vẫn là một nguồn vô tận của những lỗi tinh vi nghiêm trọng không kém . Những thứ như ssizechỉ là các bản vá và sẽ mất một thời gian (có thể là "mãi mãi") cho đến khi điều này chìm vào "hướng dẫn thực hành tốt nhất" phổ biến mà mọi người (có thể) tuân theo một cách nghiêm ngặt.
Marco 13

6
@ Marco13: Mặt khác, hệ thống kiểu C / C ++ (trái ngược với hệ thống kiểu cố định của Java), ngoài việc cho phép mã C / C ++ hoạt động trên các kiến ​​trúc mà hầu hết các ngôn ngữ khác không có , còn cho phép những người hướng dẫn có thẩm quyền có được một số điều quan trọng bài học vào đầu học sinh. Giống như, không phải tất cả thế giới đều là 64bit. Và không, không phải tất cả thế giới đều sử dụng ký tự 8-bit. Thật dễ dàng để đối phó với những điều này, nó khiến bạn trở thành một nhà phát triển tốt hơn, nếu chỉ có người hướng dẫn dạy điều này ngay từ đầu . (Và, chỉ để chắc chắn, bạn làm biết rằng (u)intX_tloại là không bắt buộc , phải không?)
DevSolar

Câu trả lời:


69

Cơ sở lý luận được mô tả trong bài báo này . Một câu trích dẫn:

Khi span được áp dụng vào C ++ 17, nó đã sử dụng một số nguyên có dấu cả làm chỉ mục và kích thước. Một phần là điều này cho phép sử dụng "-1" làm giá trị sentinel để chỉ ra một kiểu mà kích thước của nó không được biết tại thời điểm biên dịch. Nhưng có một vùng chứa STL có hàm size () trả về giá trị có dấu là vấn đề, vì vậy P1089 đã được giới thiệu để "khắc phục" sự cố. Nó nhận được sự ủng hộ của đa số, nhưng không phải là tỷ lệ chênh lệch 2 ăn 1 cần thiết cho sự đồng thuận.

Bài báo này, P1227, là một đề xuất để thêm các hàm std :: ssize và thành viên ssize () không phải thành viên. Việc bao gồm những điều này sẽ làm cho một số mã đơn giản hơn nhiều và cho phép tránh được các tính toán kích thước không mong muốn không mong muốn. Ý tưởng là khả năng chống lại P1089 sẽ giảm nếu ssize () có sẵn cho tất cả các vùng chứa, cả thông qua std :: ssize () và dưới dạng các hàm thành viên.


30
Các for(int i = 0; i < container.ssize() - 1; ++i)ví dụ cũng khá hấp dẫn
Caleth

7
@John, đối với tôi, có vẻ như họ có thể làm điều tương tự như string :: npos và chỉ sử dụng size_t (-1) làm giá trị đặc biệt.
rubenvb

15
@ JohnZ.Li Người ta coi các loại kích thước STL không có dấu từ lâu. Bây giờ tiếc là đã quá muộn để cải tổ nó. Cung cấp một chức năng miễn phí là điều tốt nhất chúng tôi có thể làm cho đến thời điểm hiện tại.
LF

16
@LF: Đó là Herb Sutter trong một hội nghị (có thể Bjarne cũng nói điều này). Nhưng, anh ấy có một chút sai lầm. Bây giờ, với máy tính 32-bit / 64-bit, kích thước ký sẽ tốt hơn (Vì vậy, anh ấy đúng). Nhưng ngày xưa (kích thước 16-bit), kích thước có dấu sẽ không tốt (ví dụ: chúng ta có thể chỉ cấp phát mảng 32k byte).
geza

11
@LF: Tôi thấy Herb đang đề cập đến vấn đề này: youtube.com/watch?v=Puio5dly9N8&t=2667 . Khi anh ấy nói rằng "không thực tế lắm", ngày nay điều đó đúng. Nhưng nó không đúng> 20 năm trước (hệ thống 16-bit) chút nào. Vì vậy, không có nhiều sai lầm khi sử dụng không dấu, khi STL được thiết kế.
geza

50

Bị đánh cắp một cách vô cớ từ Eric Niebler:

'Unsigned types signal that a negative index/size is not sane'là sự khôn ngoan thịnh hành khi STL được thiết kế lần đầu tiên. Nhưng về mặt logic, số lượng mọi thứ không cần phải tích cực. Tôi có thể muốn giữ số lượng ở dạng số nguyên có dấu để biểu thị số phần tử được thêm vào hoặc bị xóa khỏi tập hợp. Sau đó, tôi muốn kết hợp điều đó với kích thước của bộ sưu tập. Nếu kích thước của bộ sưu tập không có dấu, bây giờ tôi buộc phải kết hợp số học có dấu và không dấu, đó là một trang trại lỗi. Các trình biên dịch cảnh báo về điều này, nhưng vì thiết kế của STL khá nhiều buộc các lập trình viên vào tình huống này, cảnh báo này rất phổ biến nên hầu hết mọi người đều tắt nó đi. Thật đáng tiếc vì điều này ẩn chứa những lỗi thực sự.

Việc sử dụng int không dấu trong giao diện không phải là lợi ích mà nhiều người nghĩ. Nếu tình cờ một người dùng chuyển một số âm đến API, nó sẽ đột nhiên trở thành một số dương rất lớn. Nếu API lấy số như đã ký, thì nó có thể phát hiện tình huống bằng cách xác nhận số lớn hơn hoặc bằng không.

Nếu chúng ta hạn chế việc sử dụng các int không có dấu để làm lộn xộn (ví dụ: mặt nạ) và sử dụng các int có dấu ở mọi nơi khác, thì các lỗi sẽ ít xảy ra hơn và dễ dàng phát hiện hơn khi chúng xảy ra.


6
Swift thực hiện cách tiếp cận này, mặc dù nó không phải lo lắng về việc các số có dấu âm được diễn giải lại thành các số không có dấu khổng lồ (vì không có phôi ngầm, đó là những gì thực sự đưa bạn vào ngôi nhà thú vị điên rồ này để bắt đầu). Họ chỉ áp dụng cách tiếp cận (kích thước từ máy) Intphải là loại tiền tệ chung của các số nguyên, ngay cả khi chỉ các số dương mới có ý nghĩa (chẳng hạn như lập chỉ mục một mảng). Bất kỳ sự sai lệch nào so với nó cũng phải có cơ sở. Thật tuyệt khi không cần phải lo lắng về phôi ở mọi nơi.
Alexander - Phục hồi Monica

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.