Tại sao std :: cấp phát không phổ biến? [đóng cửa]


8

Với các xu hướng mới nhất về ứng dụng C và C ++, và với ý nghĩa mới nhất của tôi trong những năm gần đây nhất, tôi đã hy vọng sẽ thấy std::allocators được sử dụng thường xuyên hơn so với thực tế.

Các ứng dụng hiện đại thường là đa luồng hoặc có dạng đồng thời trong đó và chúng quản lý một lượng bộ nhớ đáng kể, đặc biệt là trong một số lĩnh vực như trò chơi và ứng dụng đa phương tiện; do đó, chi phí phân bổ / thỏa thuận cao thông thường tăng lên và ảnh hưởng đến hiệu suất thậm chí nhiều hơn trong các ứng dụng cũ.

Nhưng đối với những gì tôi có thể thấy loại quản lý bộ nhớ này thông qua std::allocators không phổ biến, tôi thậm chí không thể đếm được 1 thư viện mà tôi biết, đó là sử dụng bất kỳ lý do hợp lý nào về cách quản lý bộ nhớ chuẩn.

Có một lý do thực sự tại sao std::allocatorkhông phổ biến? Lý do kỹ thuật?


2
vì nó khó sử dụng?
Bryan Chen

4
@BryanChen bạn có ý gì với điều đó? bộ cấp phát thường là đối số thứ 2 trong bất kỳ vùng chứa tiêu chuẩn nào, std::allocatornó cực kỳ dễ sử dụng.
user2485710

1
Bạn có hỏi tại sao std::allocator(về cơ bản là bao bọc xung quanh newvà vị trí- new) không được sử dụng nhiều không? Hay bạn đang hỏi tại sao khái niệm C ++ của Allocatorwidley không được sử dụng? Chúng là hai câu hỏi khác nhau.
Dave S

@DaveS giống như tùy chọn đầu tiên, nhưng tôi không hiểu tại sao nó khác với tùy chọn thứ hai, ý bạn là gì đó liên quan đến tính di động của chính mã?
user2485710

1
@BryanChen bạn có thể chỉ ra tại sao nó khó không? những cạm bẫy là gì?
user2485710

Câu trả lời:


13

Có hai loại câu hỏi ở đây:

1) Tại sao không std::allocatorđược sử dụng nhiều hơn?

Câu trả lời ngắn gọn là vì hầu hết các mục đích sử dụng, sử dụng newdeletelà đủ.

Đầu tiên, một cái nhìn tổng quan ngắn gọn về khái niệm Allocator C ++ 11 dành cho mục đích gì. Về cơ bản, khi bạn thực hiện a new Foo, cả hai đều cấp phát bộ nhớ và sau đó xây dựng đối tượng trong bộ nhớ đó.

Nhưng nếu bạn cần phân bổ bộ nhớ và xây dựng thành hai bước riêng biệt. Ví dụ kinh điển về điều này là std::vector, có thể phân bổ bộ nhớ mà không cần khởi tạo nó ngay lập tức, nhưng sau đó xây dựng các phần tử khi bạn thêm chúng vào vùng chứa. Mục đích của std::allocatorviệc cung cấp một giao diện để thực hiện các bước riêng biệt đó một cách thống nhất.

Tuy nhiên, đối với hầu hết người dùng, họ không cần mức độ kiểm soát đó, bởi vì đó chỉ là một điều cần nhớ khi làm sạch các ngoại lệ của bạn.

2) Tại sao không có nhiều thứ sử dụng khái niệm C ++ Allocator?

Chủ yếu là nhu cầu không có ở đó. Các lớp duy nhất có xu hướng sử dụng chúng là những lớp muốn cung cấp cho người dùng của họ quyền kiểm soát nhiều hơn đối với nguồn bộ nhớ mà họ phân bổ. Các thùng chứa thư viện tiêu chuẩn được viết theo cách đó để người dùng có thể đưa ra các quyết định đó nếu họ chọn, nhưng họ mặc định sử dụng bộ cấp phát bình thường.


3
+1 cho điểm 1 đó là lý do thực sự theo ý kiến ​​của tôi. Không phải "nó khó sử dụng" mà tôi hoàn toàn không đồng ý khi đã viết nhiều bộ cấp phát bộ nhớ cho các nhóm bộ nhớ khác nhau: bộ cấp phát khá dễ viết và nó chỉ là một loạt các phương thức tuân thủ giao diện. Cách bạn quản lý bộ nhớ tùy thuộc vào bạn, có thể dễ hoặc có thể khó (chunk với cơ chế liên kết)
Marco A.

5

Sự phổ biến của một ngôn ngữ hoặc một khái niệm thư viện là trong một mối tương quan nghịch đảo với sự phức tạp tiềm ẩn của nó.

Đây std::allocatorlà một khái niệm cấp thấp và như vậy có những cạm bẫy tiềm năng. Có một phân bổ tùy chỉnh trả trước có khả năng được đánh giá là tối ưu hóa sớm. Hơn nữa, tương tự như các khái niệm cấp thấp khác, thường được ưu tiên ủy quyền quản lý phân bổ công việc cho các thư viện (stdlib, boost) trừ khi chi phí xử lý sự phức tạp của phân bổ của bạn được bảo đảm tuyệt đối.

Xem xét các con trỏ như chỉ là một ví dụ hỗ trợ của luận án này. Chúng tôi yêu thích con trỏ vì khả năng truy cập vào bộ nhớ và chi phí không bị hạn chế, nhưng trong C ++, chúng tôi biết rõ hơn là sử dụng các trình bao bọc có phạm vi / raii để quản lý sự phức tạp, đó là cho đến khi chúng tôi rõ ràng cần hiệu suất hoặc tất cả có thể đồng ý về một số ngữ nghĩa không sở hữu trường hợp sử dụng được xác định rõ.

Khi sử dụng std :: cấp phát bạn cần phải xem xét các ABI và sự phù hợp API, và câu hỏi tuyệt vời như hành vi mong muốn khi đang tham gia
std::vector<T,A1>().swap(std::vector<T,A2>())với nhau (và stateful!) A1A2allocators. Hơn nữa, một số container thậm chí không sử dụng bộ cấp phát theo cách bạn dự định! Hãy xem std::list<T,A>hoặc std::map<K,T,C,A>ví dụ. Kỳ vọng tự nhiên là phân bổ được sử dụng để phân bổ các đối tượng loại Tcho danh sách hoặc pair<const K,T>bản đồ, tuy nhiên trong thực tế, việc triển khai thư viện chuẩn sẽ yêu cầu phân bổ danh sách hoặc nút bản đồ và thậm chí kích thước của nút có thể khác nhau giữa các bản dựng phát hành và gỡ lỗi. Các cấp phát tùy chỉnh đầy rẫy những chi tiết vụn vặt, và sự phức tạp và chi tiết được thêm vào là không cần thiết cho các tác vụ lập trình phổ biến nhất.


Chi phí sử dụng của trình bao bọc RAII std::unique_ptr<T>để sở hữu bộ nhớ trái ngược với điều T *gì?
David Stone

@DavidStone Như tôi đoán bạn đã biết (làm cho đó là một câu hỏi mẹo), câu trả lời là không.
gạch dưới

2

Phân bổ là một chính sách được đưa vào phụ thuộc vào các thùng chứa tiêu chuẩn. Chủ yếu là cho phép mã máy khách tách chính sách phân bổ khỏi khởi tạo, trong các thùng chứa đã được triển khai .

Vấn đề xuất hiện khi bạn cần sử dụng std :: container và chính sách phân bổ mặc định (như được thực hiện bởi std :: allocator) không phù hợp với nhu cầu của dự án của bạn (ví dụ: bạn muốn triển khai std :: vector hơn 1024 đối tượng được phân bổ, bạn muốn sử dụng nhóm bộ nhớ hoặc đảm bảo tất cả các phân bổ đều được phân bổ trong một vùng nhớ nhất định, v.v.).

Nếu bạn không thể tiêm một bộ cấp phát khác vào các thùng chứa, điều này sẽ cấm bạn sử dụng std :: container hoàn toàn trong một số dự án.

Để giải quyết vấn đề này (và đảm bảo bạn vẫn có thể sử dụng std :: container khi bạn có yêu cầu bộ nhớ phức tạp), bộ cấp phát là một tham số templated cho các container.

Để trả lời câu hỏi của bạn : hầu hết mọi người không sử dụng std :: allocators vì khi họ viết mã máy khách, họ có toàn quyền kiểm soát phân bổ - vì vậy họ không cần phải tiêm chính sách phân bổ - và khi họ sử dụng mã thư viện, std :: cấp phát thường là đủ.

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.