2016-09-09 21 views
29

Đặc tả C++ 17 không dùng các thành viên constructdestroy của đối tượng std::allocator. Nhóm làm việc đã cung cấp lý do cho việc không dùng chức năng thành viên khác here, dưới tiêu đề "Không dùng các thành viên dư thừa của std :: allocator".Tại sao std :: cấu trúc cấp phát và hủy các hàm bị phản đối trong C++ 17?

Tuy nhiên, họ không đề cập cụ thể lý do tại sao hai thành viên đó không được dùng nữa hoặc đề xuất là gì để thay thế chức năng đó. Tôi giả sử ý nghĩa là sử dụng std::allocator_traits::construct thay thế.

Tôi là một chút nhầm lẫn về việc thực hiện construct có thể thực sự vẫn là cần thiết trong một số trường hợp mặc dù vì this comment about std::allocator_traits::construct

Bởi vì chức năng này cung cấp sự sụp đổ tự động trở về vị trí mới, chức năng thành viên xây dựng() là một yêu cầu Allocator tùy chọn kể từ C++ 11.

Đối với người phân bổ tùy chỉnh (ví dụ: bộ nhớ được liên kết trang sử dụng memalign), sẽ quay lại vị trí new luôn tạo ra hành vi đúng?

Trả lời

15

allocator requirements table nói rằng construct(c, args), nếu được cung cấp, phải "tạo đối tượng thuộc loại C tại c".

Nó nói hoàn toàn không có gì về 1) đối số nào sẽ được chuyển đến hàm xây dựng C hoặc 2) cách các đối số này được chuyển. Đó là sự lựa chọn của người cấp phát, và trên thực tế hai người phân bổ trong tiêu chuẩn làm lộn xộn với các đối số trước khi chuyển chúng đến một constructor C: std::scoped_allocator_adaptorstd::pmr::polymorphic_allocator. Khi xây dựng một số std::pair, đặc biệt, các đối số mà chúng truyền tới hàm tạo của pair có thể không giống với các đối số mà chúng nhận được.

Không yêu cầu phải chuyển tiếp hoàn hảo; một kiểu C++ 03 construct(T*, const T&) phù hợp nếu không hiệu quả.

constructdestroy không được chấp nhận vì chúng vô dụng: không có mã C++ 11 và mã mới hơn nên gọi trực tiếp và không thêm gì ngoài mặc định.


Xử lý căn chỉnh bộ nhớ phải là nhiệm vụ allocate, không phải construct.

7

Các chức năng đã bị xóa cùng với các chức năng khác từ giấy D0174R0 Deprecating Vestigial Library Parts in C++17. Nếu chúng tôi xem xét phần có liên quan, chúng tôi có

Nhiều thành viên của std :: phân bổ hành vi trùng lặp dư thừa khác được sản xuất bởi std::allocator_traits<allocator<T>> và có thể xóa an toàn để đơn giản hóa lớp này. Hơn nữa, địa chỉ như là một chức năng miễn phí thay thế std::allocator<T>::address mà đòi hỏi một đối tượng cấp phát của đúng loại. Cuối cùng, các bí danh kiểu tham chiếu ban đầu được cung cấp như một phương tiện dự kiến ​​để mở rộng với các trình phân bổ khác, nhưng hóa ra không phục vụ một mục đích hữu ích khi chúng tôi xác định các yêu cầu cấp phát (17.6.3.5 [allocator.requirements]).

Mặc dù chúng tôi không thể xóa các thành viên này mà không phá vỡ tính tương thích ngược với mã sử dụng loại phân bổ này một cách rõ ràng, chúng tôi không nên đề xuất việc sử dụng liên tục của chúng. Nếu một kiểu muốn hỗ trợ các trình phân bổ chung, nó sẽ truy cập chức năng của allocator thông qua allocator_traits thay vì truy cập trực tiếp vào các thành viên của cấp phát - nếu không nó sẽ không hỗ trợ đúng các trình phân bổ dựa vào các đặc tính để tổng hợp các hành vi mặc định. Tương tự, nếu người dùng không có ý định hỗ trợ các trình phân bổ chung, thì việc gọi trực tiếp mới, xóa và giả định các thuộc tính khác của std :: allocator như trực tiếp các kiểu con trỏ là đơn giản hơn nhiều.

tôi nhấn mạnh

Vì vậy, hợp lý là chúng ta không cần phải lặp lại tất cả các mã trong cấp phát vì chúng ta có những đặc điểm cấp phát. Nếu chúng ta nhìn vào std::allocator_traits, chúng ta sẽ thấy rằng nó có

allocate 
deallocate 
construct 
destroy 
max_size 

chức năng tĩnh để chúng ta có thể sử dụng chúng thay cho những cái trong bộ cấp phát.

+0

vâng tôi đã nói khá nhiều trong câu hỏi. –

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