सी ++ 11 खंड 17.6.3.5 आवंटन आवश्यकताओं [allocator.requirements] आवंटकों को अनुरूप बनाने के लिए आवश्यकताओं को निर्दिष्ट करता है। आवश्यकताओं में से हैं:
X an Allocator class for type T
...
a, a1, a2 values of type X&
...
a1 == a2 bool returns true only if storage
allocated from each can be
deallocated via the other.
operator== shall be reflexive,
symmetric, and transitive, and
shall not exit via an exception.
...
X a1(a); Shall not exit via an exception.
post: a1 == a
आईई। जब आप एक आवंटक की प्रतिलिपि बनाते हैं, तो दो प्रतियों को एक-दूसरे के पॉइंटर्स को हटाने में सक्षम होना आवश्यक होता है।
निश्चित रूप से कोई भी आंतरिक बफर आवंटकों में डाल सकता है, लेकिन प्रतियों को अन्य बफर की सूची रखना होगा। या शायद एक आवंटक के पास एक आविष्कार हो सकता है कि डीलोकेशन हमेशा एक नो-ऑप होता है क्योंकि सूचक हमेशा आंतरिक बफर से आता है (या तो स्वयं से, या किसी अन्य प्रतिलिपि से)।
लेकिन जो कुछ भी योजना है, प्रतियां "पार-संगत" होना चाहिए।
अद्यतन
यहाँ एक सी ++ 11 अनुरूप संभाजक कि "छोटे स्ट्रिंग अनुकूलन" करता है।
#include <cstddef>
template <std::size_t N>
class arena
{
static const std::size_t alignment = 16;
alignas(alignment) char buf_[N];
char* ptr_;
std::size_t
align_up(std::size_t n) {return n + (alignment-1) & ~(alignment-1);}
public:
arena() : ptr_(buf_) {}
arena(const arena&) = delete;
arena& operator=(const arena&) = delete;
char* allocate(std::size_t n)
{
n = align_up(n);
if (buf_ + N - ptr_ >= n)
{
char* r = ptr_;
ptr_ += n;
return r;
}
return static_cast<char*>(::operator new(n));
}
void deallocate(char* p, std::size_t n)
{
n = align_up(n);
if (buf_ <= p && p < buf_ + N)
{
if (p + n == ptr_)
ptr_ = p;
}
else
::operator delete(p);
}
};
template <class T, std::size_t N>
class stack_allocator
{
arena<N>& a_;
public:
typedef T value_type;
public:
template <class U> struct rebind {typedef stack_allocator<U, N> other;};
explicit stack_allocator(arena<N>& a) : a_(a) {}
template <class U>
stack_allocator(const stack_allocator<U, N>& a)
: a_(a.a_) {}
stack_allocator(const stack_allocator&) = default;
stack_allocator& operator=(const stack_allocator&) = delete;
T* allocate(std::size_t n)
{
return reinterpret_cast<T*>(a_.allocate(n*sizeof(T)));
}
void deallocate(T* p, std::size_t n)
{
a_.deallocate(reinterpret_cast<char*>(p), n*sizeof(T));
}
template <class T1, std::size_t N1, class U, std::size_t M>
friend
bool
operator==(const stack_allocator<T1, N1>& x, const stack_allocator<U, M>& y);
template <class U, std::size_t M> friend class stack_allocator;
};
template <class T, std::size_t N, class U, std::size_t M>
bool
operator==(const stack_allocator<T, N>& x, const stack_allocator<U, M>& y)
{
return N == M && &x.a_ == &y.a_;
}
template <class T, std::size_t N, class U, std::size_t M>
bool
operator!=(const stack_allocator<T, N>& x, const stack_allocator<U, M>& y)
{
return !(x == y);
}
यह इस तरह इस्तेमाल किया जा सकता: यह सी ++ 11 अनुरूप बनाने के लिए, मैं डाल करने के लिए "आंतरिक" संभाजक के लिए बाहरी बफ़र ताकि प्रतियां बराबर हैं पड़ा
#include <vector>
template <class T, std::size_t N> using A = stack_allocator<T, N>;
template <class T, std::size_t N> using Vector = std::vector<T, stack_allocator<T, N>>;
int main()
{
const std::size_t N = 1024;
arena<N> a;
Vector<int, N> v{A<int, N>(a)};
v.reserve(100);
for (int i = 0; i < 100; ++i)
v.push_back(i);
Vector<int, N> v2 = std::move(v);
v = v2;
}
सभी उपरोक्त समस्या के लिए आवंटन स्थानीय arena
से खींचे गए हैं जो आकार में 1 Kb है। आप इस आवंटक को मूल्य या संदर्भ के आधार पर पास करने में सक्षम होना चाहिए।
क्या आप कृपया जो कुछ करने का प्रयास कर रहे हैं उसके कुछ विवरण जोड़ सकते हैं? आपको स्पष्ट रूप से राज्य के आवंटकों से सावधान रहना होगा, लेकिन कुछ मानक संचालन जैसे कि एक कंटेनर को दूसरे से स्थानांतरित करना मानक मुहावरे हैं। –
@KerrekSB: आह, ठीक है। उदाहरण के लिए, मैं "प्रतिलिपि 'या' आरक्षित 'ऑपरेशन ऑपरेशन को" कॉपी-इन-कंटेनर-एंड-स्वैप "ऑपरेशन के रूप में कार्यान्वित करने की कोशिश कर रहा हूं। यह काम करता है, अगर आवंटक के पास अपना स्वयं का मेमोरी पूल नहीं है। (यदि ऐसा होता है, तो मैं दो बार स्वैप कर सकता हूं, लेकिन एक प्रतिलिपि बनाना अभी भी महंगा हो सकता है और यदि इसमें अपना पूल होता है तो स्टैक ओवरफ़्लो हो सकता है।) – Mehrdad