2011-12-19 36 views
7

Hãy nói rằng tôi có thể tạo một danh sách liên kết trong STL:Các phân bổ tùy chỉnh trong STL chỉ phân bổ dữ liệu thực tế?

list<int, my_allocator<int> > data; 

Sau đó, tôi có thể sử dụng một cấp phát hiệu quả hơn, chúng ta hãy nói một hồ bơi bộ nhớ. Nhưng không danh sách cần phải phân bổ bộ nhớ trong như con trỏ tiến và lùi để duyệt qua danh sách? Chúng sẽ được phân bổ như thế nào? Sử dụng bình thường new hoặc bằng cách nào đó sử dụng my_allocator?

+0

Bạn có nghĩa là triển khai STL hoặc Thư viện chuẩn C++ đi kèm với chuỗi công cụ bạn đã chọn không? Và cái nào vậy? –

+0

@ TomalakGeret'kal, cái gì? (+1 cho câu hỏi) – avakar

+0

@avakar STL ban đầu là một dự án sgi. Kể từ đó đã có một số triển khai của STL (chẳng hạn như STLport) và phần lớn nó đã được thêm vào thư viện chuẩn theo quy định của ủy ban, mặc dù với một vài thay đổi. Tất cả đều để lại * "STL" * một chút không rõ ràng theo những cách có thể ảnh hưởng đến câu hỏi này. – dmckee

Trả lời

10

Vùng chứa thực sự sử dụng lại trình phân bổ của bạn để phân bổ tài liệu lưu giữ sách của riêng mình. (Không phải là nó sẽ thành vấn đề đối với một std::list, nhưng đó là sự thật nói chung *.) Đây là lý do tại sao các yêu cầu cấp phát tiêu chuẩn uỷ quyền cho sự tồn tại của rebind mẫu:

typedef typename Alloc::template rebind<MyInternalStuff>::other internal_allocator; 

Nếu cấp phát của bạn là Alloc = my_allocator<T>, sau đó internal_allocator trở thành my_allocator<MyInternalStuff> .

Tôi tin rằng đây là một trong những điều mà Electronic Arts đã có với thư viện chuẩn C++, đó là lý do tại sao thư viện EASTL của họ sử dụng một quy ước khác cho người cấp phát có kiểm soát chặt hơn.

*) Thông thường, mỗi nút sẽ là một đối tượng nguyên khối của một số loại Node<T>, vì vậy tôi cho rằng std::list<T, Alloc>chỉ bao giờ sử dụng Alloc::rebind<Node<T>>::other như một cấp phát.

[Xin lỗi vì đã chỉnh sửa nhiều lần; Tôi có đầu ra bị xáo trộn và không giải thích nó một cách chính xác; Bây giờ tôi đã đi và in từng thùng chứa một cách riêng biệt và cố định đầu ra cho phù hợp. std::list không thực sự chỉ cần một cấp phát]


Cập nhật:. Chỉ cần cho tiếng cười khúc khích, tôi đã viết một chút demangling-cấp phát mà in typename riêng của mình khi xây dựng. Dưới đây là các đầu vào:

#include <unordered_map> 
#include <set> 
#include <deque> 
#include <list> 
#include <vector> 
#include <map> 

#include <iostream> 

int main() 
{ 
    std::cout << "----- unordered_map<int, double> -----------" << std::endl; 
    std::unordered_map<int, double, std::hash<int>, std::equal_to<int>, funky_allocator<std::pair<const int, double>>> m { {1, 1.2} }; 
    std::cout << "----- set<int> -----------------------------" << std::endl; 
    std::set<int, std::less<int>, funky_allocator<int>> s; 
    std::cout << "----- deque<int> ---------------------------" << std::endl; 
    std::deque<int, funky_allocator<int>> d; 
    std::cout << "----- list<int> ----------------------------" << std::endl; 
    std::list<int, funky_allocator<int>> l; 
    std::cout << "----- vector<int> --------------------------" << std::endl; 
    std::vector<int, funky_allocator<int>> c; 
    std::cout << "----- map<int, bool> -----------------------" << std::endl; 
    std::map<int, bool, std::less<int>, funky_allocator<std::pair<const int, bool>>> n { { 1, true } }; 
} 

Và đây là kết quả:

----- unordered_map<int, double> ----------- 
Default-construct: funky_allocator<std::pair<int const, double> > 
Copy-construct: funky_allocator<std::__detail::_Hash_node<std::pair<int const, double>, false> > 
Copy-construct: funky_allocator<std::__detail::_Hash_node<std::pair<int const, double>, false>*> 

----- set<int> ----------------------------- 
Default-construct: funky_allocator<std::_Rb_tree_node<int> > 

----- deque<int> --------------------------- 
Default-construct: funky_allocator<int> 
Copy-construct: funky_allocator<int*> 

----- list<int> ---------------------------- 
Default-construct: funky_allocator<std::_List_node<int> > 

----- vector<int> -------------------------- 
Default-construct: funky_allocator<int> 

----- map<int, bool> ----------------------- 
Default-construct: funky_allocator<std::_Rb_tree_node<std::pair<int const, bool> > > 

Các chi tiết khác nhau tùy thuộc vào constructor được sử dụng: Container như setmap chỉ có thể xây dựng "đúng" cấp phát trong một số gọi, trong khi khác, họ có thể xây dựng một đối tượng của các cấp phát được chỉ định đầu tiên. Dù bằng cách nào, phân bổ được chỉ định không bao giờ được sử dụng ở tất cả cho một vài vùng chứa và chỉ chỉ phiên bản phục hồi được sử dụng.

+0

Cảm ơn bạn-biết-những gì;) –

+0

+1, mặc dù bạn đang thiếu 'template' trước' rebind' :) – avakar

+0

@avakar: Bạn nói đúng, tôi vừa để ý điều đó! Trong thực tế, tôi chỉ viết phân bổ demangling của riêng tôi mà in tên lớp riêng của nó khi instantiation để kiểm tra có bao nhiêu phân bổ khác nhau một số container phổ biến yêu cầu. –

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