অ্যালোকেটর (সি++)

সি++ প্রোগ্রামিং ল্যাঙ্গুয়েজ এ, অ্যালোকেটর হল সি++ স্ট্যান্ডার্ড লাইব্রেরির গুরুত্বপূর্ণ অংশ। এই লাইব্রেরিটি লিস্ট এবং সেট এর মত আরও গুরুত্বপূর্ণ কিছু ডেটা স্ট্রাকচার প্রদান করে, সাধারণভাবে যাদের কন্টেইনার বলা হয়ে থাকে। এই কন্টেইনারগুলোর একটি সাধারণ ফিচার হচ্ছে রান টাইমে আকার পরিবর্তন করা, যা অর্জন করা হয় ডাইনামিক মেমরি অ্যালোকেশন এর মাধ্যমে। একটি কন্টেইনার এর মেমোরিতে স্থান নির্ধারণ এবং অপসারণ, অ্যালোকেটর পরিচালনা করে থাকে। সি++ স্ট্যান্ডার্ড লাইব্রেরি সাধারণ ব্যবহার্য অ্যালোকেটর প্রদান করে থাকে, আবার একজন প্রোগ্রামারও তার নিজস্ব অ্যালকেটর সরবরাহ করতে পারেন।
সি++ স্ট্যান্ডার্ড স্ট্যান্ডার্ড লাইব্রেরির অংশ হিসেবে অ্যালেকজান্ডার স্টেপানভ অ্যালোকেটর উদ্ভাবন করেন। এর মূল উদ্দেশ্য ছিল লাইব্রেরিটিকে আরও সহজলভ্য এবং মুল মেমোরি মডেল থেকে স্বাধীন করা, যাতে প্রোগ্রামাররা লাইব্রেরির সাথে নিজস্ব পয়েন্টার এবং রেফারেন্স টাইপ ব্যবহার করতে পারেন। এস,টি,এল কে সি++
স্ট্যান্ডার্ডে গ্রহণ করার প্রক্রিয়ায়, সি++ মান নির্ধারণ পরিষদ উপলব্ধি করে যে, মেমোরি মডেলের পূর্ণ বিমূর্তণ অপ্রীতিকর কর্মসম্পাদন সাধন করতে পারে। এর বিহিত করার জন্য, অ্যালোকেটরের আবশ্যিকতা নিয়ন্ত্রণ করা হয়েছে। এর ফলে, স্টেপানভের প্রকৃত উদ্ভাবনের চেয়ে নিজস্ব অ্যালোকেটরের ব্যবহার অত্যন্ত সীমিত।
তা সত্ত্বেও, কিছু ক্ষেত্রে নিজস্ব অ্যালোকেটরের ব্যবহারই কাম্য। নিজস্ব অ্যালোকেটর লেখার কিছু সাধারণ কারণ হল মেমোরি পুল ব্যবহার করে মেমোরিতে স্থান নির্ধারণের গতি উন্নতি করা, এবং বিভিন্ন ধরনের মেমোরির প্রবেশাধিকার সংরক্ষণ করা যেমন শেয়ারকৃত মেমোরি অথবা গারবেজ-সংগৃহীত মেমোরি। প্রকৃতপক্ষে, যেসকল প্রোগ্রাম স্বল্প মেমোরি বারংবার নির্ধারণ করে থাকে, সেগুলো বিশেষায়িত অ্যালোকেটর এর উপকারিতা লাভ করতে পারে রান টাইম এবং মেমোরি ফুটপ্রিন্ট এর ক্ষেত্রে।
অ্যালেকজান্ডার স্টেপানভ এবং মেং লী ১৯৯৪ সালের মার্চ মাসে সি++ মান নির্ধারক পরিষদের কাছে স্ট্যান্ডার্ড টেম্পলেট লাইব্রেরী (এস,টি,এল) উপস্থাপন করেন। বেশ কিছু ইস্যু থাকা সত্ত্বেও লাইব্রেরিটি প্রাথমিক অনুমোদন পায়। প্রকৃতপক্ষে, স্টেপানভকে লাইব্রেরী কন্টেইনারগুলোকে মূল মেমোরি মডেল থেকে স্বাধীন করার জন্য অনূরোধ করা হয়েছিল, যা থেকেই মূলতঃ অ্যালোকেটর উদ্ভাবিত হয়। ফলস্বরূপ, সকল এস,টি,এল কন্টেইনার ইন্টারফেসগুলোকে আবার নতুন ভাবে লিখতে হয়েছিল যাতে তারা অ্যালোকেটর গ্রহণ করতে পারে।
এস,টি,এল কে সি++ স্ট্যান্ডার্ড লাইব্রেরিতে অন্তর্ভুক্তির কাজে স্টেপানভ মান নির্ধারক পরিষদের কয়েকজন সদস্যদের সাথে ঘনিষ্ঠভাবে কাজ করেছেন, অ্যান্ড্রু কেইনিগ এবং বিয়ারনে স্ট্রোভস্ট্রুপ তাদের মধ্যে অন্যতম, যারা লক্ষ্য করেন যে রূপান্তরিত অ্যালোকেটরসমূহকে ব্যবহার করা যেতে পারে স্থায়ী স্টোরেজ এস,টি,এল কন্টেইনার সম্পাদনের ক্ষেত্রে, যেটা সেসময় স্টেপানভ "গুরুত্বপূর্ণ এবং কৌতূহল উদ্দীপক দূরদৃষ্টি" হিসেবে বিবেচনা করেন।
মূল অ্যালোকেটরের প্রস্তাবে প্রোগ্রামিং ভাষার কিছু বৈশিষ্ট্য অন্তর্ভুক্ত ছিল যা এখনও পরিষদ দ্বারা গৃহীত হয় নাই, যেমন টেম্পলেট আর্গুমেন্ট ব্যবহার করা যারা নিজেরাই টেম্পলেট। যেহেতু এইসব বৈশিষ্ট্য বিদ্যমান কোনো কম্পাইলার কম্পাইল করতে পারে না, তখন স্টেপানভের মতে, "অসম্পাদিত বৈশিষ্ট্যগুলো আমরা সঠিক ভাবে ব্যবহার করি তা যাচাই করতে বিয়ারনে স্ট্রোভস্ট্রুপ এবং অ্যান্ড্রু কেইনিগ প্রচুর সময়ের প্রয়োজন ছিল।" লাইব্রেরিটি ইতিপূর্বে পয়েন্টার এবং রেফারেন্স টাইপ সরাসরি ব্যবহার করছিল, এটা এখন শুধুমাত্র অ্যালোকেটর দ্বারা সংজ্ঞায়িত টাইপসমূহকেই নির্দেশ করতে পারে। স্টেপানভ পরে অ্যালোকেটরের বর্ণনা দেন এরকমঃ "এস,টি,এল এর একটি চমৎকার বৈশিষ্ট্য হচ্ছে যে স্থানে মেশিন-সংশ্লিষ্ট টাইপ উল্লেখ করা হয় তা মোটামুটি ১৬ লাইন কোডের মধ্যে নিরাপদে আছে।"
যদিও স্টেপানভ মেমোরি মডেলের পরিপূর্ণ নিরাপত্তা মূলত অ্যালোকেটরসমূহের দ্বারা সঙ্কল্পিত করেন, মান নির্ধারক কমিটি উপলব্ধি করে যে এই উপায় অপ্রীতিকর কার্যকারিতা অবক্ষয়ের দিকে নিয়ে যেতে পারে। এর প্রতিকার করার জন্য, অতিরিক্ত বাক্য অ্যালোকেটরসমূহের আবশ্যিকতায় যুক্ত করা হয়। নির্দিষ্টভাবে, কনটেইনার এর বাস্তবায়ন এটা মনে করতে পারে যে, পয়েন্টার এবং ইন্টেজার টাইপের জন্য অ্যালোকেটরের সংজ্ঞা ডিফল্ট অ্যালোকেটরের সমতুল্য।,
In particular, container implementations may assume that the allocator's type definitions for pointers and related integral types are equivalent to those provided by the default allocator, and that all instances of a given allocator type always compare equal, effectively contradicting the original design goals for allocators and limiting the usefulness of allocators that carry state.
Stepanov later commented that, while allocators "are not such a bad [idea] in theory (...) [u]nfortunately they cannot work in practice". He observed that to make allocators really useful, a change to the core language with regards to references was necessary.
The 2011 revision of the C++ Standard removed the weasel words requiring that allocators of a given type always compare equal and use normal pointers. These changes make stateful allocators much more useful and allow allocators to manage out-of-process shared memory. The current purpose of allocators is to give the programmer control over memory allocation within containers, rather than to adapt the address model of the underlying hardware. In fact, the revised standard eliminated the ability of allocators to represent extensions to the C++ address model, formally (and deliberately) eliminating their original purpose.
Any class that fulfills the "allocator requirements" can be used as an allocator. In particular, a class codice_1 capable of allocating memory for an object of type codice_2 must provide the types codice_3, codice_4, codice_5, codice_6, and codice_7 for generically declaring objects and references (or pointers) to objects of type codice_2. It should also provide type codice_9, an unsigned type which can represent the largest size for an object in the allocation model defined by codice_1, and similarly, a signed integral codice_11 that can represent the difference between any two pointers in the allocation model.
Although a conforming standard library implementation is allowed to assume that the allocator's codice_3 and codice_4 are simply typedefs for codice_14 and codice_15, library implementors are encouraged to support more general allocators.
An allocator, codice_1, for objects of type codice_2 must have a member function with the signature codice_18. This function returns a pointer to the first element of a newly allocated array large enough to contain codice_19 objects of type codice_2; only the memory is allocated, and the objects are not constructed. Moreover, an optional pointer argument (that points to an object already allocated by codice_1) can be used as a hint to the implementation about where the new memory should be allocated in order to improve locality. However, the implementation is free to ignore the argument.
The corresponding codice_22 member function accepts any pointer that was returned from a previous invocation of the codice_23 member function and the number of elements to deallocate (but not destruct).
The codice_24 member function returns the largest number of objects of type codice_2 that could be expected to be successfully allocated by an invocation of codice_23; the value returned is typically codice_27. Also, the codice_28 member function returns an codice_3 denoting the address of an object, given an codice_5.
Object construction and destruction is performed separately from allocation and deallocation. The allocator is required to have two member functions, codice_31 and codice_32, which handles object construction and destruction, respectively. The semantics of the functions should be equivalent to the following:
template <typename T>
template <typename T>
The above code uses the placement codice_33 syntax, and calls the destructor directly.
Allocators should be copy-constructible. An allocator for objects of type codice_2 can be constructed from an allocator for objects of type codice_35. If an allocator, codice_1, allocates a region of memory, codice_37, then codice_37 can only be deallocated by an allocator that compares equal to codice_1.
Allocators are required to supply a template class member codice_40, which enables the possibility of obtaining a related allocator, parameterized in terms of a different type. For example, given an allocator type codice_41 for objects of type codice_42, a related allocator type for objects of type codice_43 could be obtained using codice_44.
One of the main reasons for writing a custom allocator is performance. Utilizing a specialized custom allocator may substantially improve the performance or memory usage, or both, of the program. The default allocator uses codice_45 to allocate memory.<ref name="C++03 20.4.1.1/3">ISO/IEC (2003). "ISO/IEC 14882:2003(E): Programming Languages - C++ §20.4.1.1 allocator members [lib.allocator.members]" para. 3</ref> This is often implemented as a thin layer around the C heap allocation functions, which are usually optimized for infrequent allocation of large memory blocks. This approach may work well with containers that mostly allocate large chunks of memory, like vector and deque. However, for containers that require frequent allocations of small objects, such as map and list, using the default allocator is generally slow. Other common problems with a malloc-based allocator include poor locality of reference, and excessive memory fragmentation.
A popular approach to improve performance is to create a memory pool-based allocator. Instead of allocating memory every time an item is inserted or removed from a container, a large block of memory (the memory pool) is allocated beforehand, possibly at the startup of the program. The custom allocator will serve individual allocation requests by simply returning a pointer to memory from the pool. Actual deallocation of memory can be deferred until the lifetime of the memory pool ends. An example of memory pool-based allocators can be found in the Boost C++ Libraries.
Another viable use of custom allocators is for debugging memory-related errors. This could be achieved by writing an allocator that allocates extra memory in which it places debugging information. Such an allocator could be used to ensure that memory is allocated and deallocated by the same type of allocator, and also provide limited protection against overruns.
The subject of custom allocators has been treated by many C++ experts and authors, including Scott Meyers in "Effective STL" and Andrei Alexandrescu in "Modern C++ Design". Meyers emphasises that C++98 requires all instances of an allocator to be equivalent, and notes that this in effect forces portable allocators to not have state. Although the C++98 Standard did encourage library implementors to support stateful allocators, Meyers calls the relevant paragraph "a lovely sentiment" that "offers you next to nothing", characterizing the restriction as "draconian".
In The C++ Programming Language, Bjarne Stroustrup, on the other hand, argues that the "apparently [d]raconian restriction against per-object information in allocators is not particularly serious", pointing out that most allocators do not need state, and have better performance without it. He mentions three use cases for custom allocators, namely, memory pool allocators, shared memory allocators, and garbage collected memory allocators. He presents an allocator implementation that uses an internal memory pool for fast allocation and deallocation of small chunks of memory, but notes that such an optimization may already be performed by the allocator provided by the implementation.
When instantiating one of the standard containers, the allocator is specified through a template argument, which defaults to codice_46:
namespace std {
Like all C++ class templates, instantiations of standard library containers with different allocator arguments are distinct types. A function expecting an codice_47 argument will therefore only accept a codice_48 instantiated with the default allocator.
The C++11 standard has enhanced the allocator interface to allow "scoped" allocators, so that containers with "nested" memory allocations, such as vector of strings or a map of lists of sets of user-defined types, can ensure that all memory is sourced from the container's allocator.
//__gnu_cxx::new_allocator< typename > Class Template Reference
//https://gcc.gnu.org/onlinedocs/gcc-4.9.0/libstdc++/api/a00057.html
java@debian:~/java/eclipse$ ldd /usr/lib/i386-linux-gnu/libstdc++.so.6.0.20
using namespace std;
using namespace __gnu_cxx;
class RequiredAllocation
public:
RequiredAllocation::RequiredAllocation ()
RequiredAllocation::~RequiredAllocation ()
void alloc(__gnu_cxx ::new_allocator<RequiredAllocation>* all, unsigned int size, void* pt, RequiredAllocation* t){
int
main ()