2013-05-03 32 views
24

Vì vậy, tôi đã xem xét đặc điểm kỹ thuật của std::vector và nhận thấy rằng reference typedef đã thay đổi từ Allocator::reference trong C++ 03 thành value_type& trong C++ 11. Tôi đã rất ngạc nhiên, vì vậy tôi đã bắt đầu nhìn sâu hơn.Tại sao Allocator :: tham chiếu bị loại bỏ?

Trong C++ 03 §20.1.5 [lib.allocator.requirements] có bảng 32 trong đó X::reference được định nghĩa là T&X::const_reference được định nghĩa là T const&.

Tuy nhiên, trong C++ 11 §17.6.3.5 [allocator.requirements] có bảng 28 trong đó thiếu referenceconst_reference.

Tiếp theo chúng tôi có §20.6.8 std::allocator_traits được thêm vào trong C++ 11 không bao gồm reference. Nhưng §20.6.9 std::allocator.

Cuối cùng, có §23.2.1 [container.requirements.general] mà xác định X::reference là "vế trái của T" và X::const_reference là "giá trị trái const của T".

Vì vậy, tôi đã tìm kiếm và tìm thấy bài báo này (1, 2) đề xuất xóa reference khỏi các yêu cầu cấp phát nhưng không đề cập đến bất kỳ lý do nào đằng sau nó. Nhưng cũng có một số LWG issue phản đối thay đổi.

Ngoài ra, tôi đã tìm thấy the interview with Alexander Stepanov trong đó ông nói như thế nào reference gói gọn bố trí bộ nhớ máy cụ thể và Herb Sutter's post trong đó ông nói về việc con trỏ đến các yếu tố container, yêu cầu container và cách std::vector<bool> không phải là một container.

Vì vậy, bạn nghĩ gì về tất cả những điều này? Là reference hữu ích, nó có phục vụ mục đích của nó không? Các tham chiếu "ưa thích" phù hợp với tiêu chuẩn như thế nào? Đây có phải là một động thái táo bạo để loại bỏ hoàn toàn chúng, đưa ra các yêu cầu nghiêm ngặt về thùng chứa hơn và không dùng nữa std::vector<bool>?

+6

câu hỏi được nghiên cứu độc đáo – David

+0

Không, nó không phải là rất đậm. Tôi sẽ phá vỡ xây dựng nếu ai đó cố gắng để nhanh chóng std :: vector

Trả lời

1

Trong the interview with Alexander Stepanov, ông đề cập rằng trong khi đề xuất thêm STL vào thư viện Chuẩn, ông được yêu cầu tạo một trừu tượng từ mô hình bộ nhớ. Vì vậy, các cấp phát đã được sinh ra. Trong các LWG issue có một ví dụ về thực hiện nơi reference của phân bổ tùy chỉnh được định nghĩa là T __far&.

Nhưng, không rõ lý do vì tôi không có nhiều thời gian để tìm kiếm, tiêu chuẩn C++ 03 có văn bản sau đây trong §20.1.5 p4:

Triển khai các container được mô tả trong này Tiêu chuẩn quốc tế được phép giả định rằng tham số mẫu Allocator của họ đáp ứng hai yêu cầu bổ sung sau vượt quá các yêu cầu trong Bảng 32.

- Tất cả các trường hợp của một loại cấp phát nhất định được yêu cầu phải hoán đổi cho nhau và luôn luôn so sánh tương đương với lẫn nhau.

- Con trỏ thành viên typedef, const_pointer, size_type và differ_type là bắt buộc phải là T *, T const *, size_t và ptrdiff_t tương ứng.

Điều này có hiệu quả đánh bại khả năng phân bổ mô hình bộ nhớ tùy chỉnh để tương thích với vùng chứa chuẩn.

Trong khi tìm kiếm tất cả các giấy tờ trước C++ 11 đề cập đến từ "cấp phát", tôi đã tìm thấy một sự đồng thuận chính để xóa những từ đó khỏi Chuẩn. Cuối cùng, this paper đề xuất xóa chúng bằng bình luận sau:

Từ chồn đã biến mất. Nâng ly và làm bánh mì nướng.

Chiến thắng? Cuối cùng chúng ta có thể đi hoang dã với các mô hình bộ nhớ của chúng ta không? Không quá nhiều. Trong số những thứ khác, cùng một giấy đề xuất để loại bỏ reference từ yêu cầu cấp phát. Và có vẻ như nó đã được bình chọn vào Tiêu chuẩn.

Các LWG issue tôi đã đề cập trước đó phản đối việc thay đổi nhưng nó đã khép lại với tuyên bố sau:

Không đồng thuận để thực hiện một sự thay đổi

Vì vậy, nó trông giống như mục đích ban đầu của allocators không phải là hôm nay rất quan trọng. Dưới đây là những gì Wikipedia phải nói:

Mục đích hiện tại của người cấp phát là cung cấp cho người lập trình kiểm soát việc cấp phát bộ nhớ trong bộ chứa, thay vì điều chỉnh mô hình địa chỉ của phần cứng cơ bản. Trong thực tế, tiêu chuẩn sửa đổi loại bỏ khả năng phân bổ để đại diện cho phần mở rộng cho mô hình địa chỉ C++, chính thức (và cố ý) loại bỏ mục đích ban đầu của chúng.

Cuối cùng, Container::reference không liên quan gì đến người cấp phát. Nó được tạo ra để cho phép các bộ sưu tập được ủy quyền which are not actually containers. Vì vậy, nó ở đây để ở. Nhân tiện, có vẻ như đây là một ví dụ khác về cách các từ cuối cùng trong Tiêu chuẩn đi ngược lại ý định ban đầu.

+1

"vì lý do không xác định" nhưng được liệt kê ở đoạn thứ hai của trang wikipedia ... –

4

Bởi vì typedef lồng nhau đó là thừa. Scott Meyers' STL hiệu quả, trang 49:

Standard rõ ràng cho phép người thực hiện thư viện cho rằng con trỏ typedef của mỗi cấp phát là một từ đồng nghĩa với T * và typedef tham khảo mỗi cấp phát là giống như T &

+0

Giấy tôi liên kết để thực sự đề xuất việc loại bỏ điều này khỏi Tiêu chuẩn. – Lyberta

+0

Nó có khả năng là một sự thay đổi phá vỡ, do đó, chúng có thể giẫm lên từ từ, giải phóng tài liệu tham khảo từ vector và tương tự. Tuy nhiên, tôi ủng hộ việc loại bỏ bất kỳ/tất cả sự mơ hồ khỏi tiêu chuẩn. –

2

http://en.wikipedia.org/wiki/Allocator_(C%2B%2B)

"Họ đang dự định ban đầu như một phương tiện để làm cho thư viện linh hoạt hơn và không phụ thuộc vào mô hình bộ nhớ nằm bên dưới, cho phép các lập trình viên sử dụng con trỏ tùy chỉnh và tham khảo các loại với thư viện. Tuy nhiên, trong quá trình áp dụng STL vào tiêu chuẩn C++, ủy ban tiêu chuẩn hóa C++ nhận ra rằng sự trừu tượng hoàn chỉnh của mô hình bộ nhớ sẽ phải chịu các hình phạt hiệu suất không thể chấp nhận được. Để khắc phục điều này, các yêu cầu của người cấp phát đã bị hạn chế hơn. bởi các nhà phân bổ là hạn chế hơn so với ban đầu được hình dung bởi Stepanov."

Nguyên chúng được thiết kế để tóm tắt đi bộ nhớ riêng của mình, cho phép một để cấp phát bộ nhớ trên nói rằng, máy khác thông qua và kết nối internet, và sao chép dữ liệu qua lại sử dụng con trỏ/tham chiếu để theo dõi các nội dung trực tiếp Tương tự như vậy, người ta có thể tạo ra một GC giống như Java trong C++ thuần túy. Sự trừu tượng này dường như là một ý tưởng tuyệt vời! rất gần như không thể làm việc trong mã. Mỗi void func(const string&) sẽ phải được thực hiện thành một template<class allocator> void func(allocator::reference), đây là một ngữ cảnh không thể suy luận để bạn có thể ve để viết rõ ràng các cấp phát trong cuộc gọi chức năng (func<std::allocator<std::string>::const_reference>(username)), mà không ai sẽ làm, mà sẽ làm cho GC không hoạt động đúng. Ngày nay, phân bổ chỉ đơn thuần là phân bổ bộ nhớ trừu tượng/deallocation.

Các vấn đề liên quan