Bu soru, bir std :: haritasına yerleştirme sırasında özel ayırıcının örneklerinin oluşturulmasıyla ilgilidir. İşte STL eşleştiricisi için Özel Bellek Ayırıcı
kullanır küçük program ile birliktestd::map<int,int>
için özel bir ayırıcı: İşte
#include <stddef.h>
#include <stdio.h>
#include <map>
#include <typeinfo>
class MyPool {
public:
void * GetNext() {
return malloc(24);
}
void Free(void *ptr) {
free(ptr);
}
};
template<typename T>
class MyPoolAlloc {
public:
static MyPool *pMyPool;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template<typename X>
struct rebind
{ typedef MyPoolAlloc<X> other; };
MyPoolAlloc() throw() {
printf("-------Alloc--CONSTRUCTOR--------%08x %32s\n", this, typeid(T).name());
}
MyPoolAlloc(const MyPoolAlloc&) throw() {
printf(" Copy Constructor ---------------%08x %32s\n", this, typeid(T).name());
}
template<typename X>
MyPoolAlloc(const MyPoolAlloc<X>&) throw() {
printf(" Construct T Alloc from X Alloc--%08x %32s %32s\n", this, typeid(T).name(), typeid(X).name());
}
~MyPoolAlloc() throw() {
printf(" Destructor ---------------------%08x %32s\n", this, typeid(T).name());
};
pointer address(reference __x) const { return &__x; }
const_pointer address(const_reference __x) const { return &__x; }
pointer allocate(size_type __n, const void * hint = 0) {
if (__n != 1)
perror("MyPoolAlloc::allocate: __n is not 1.\n");
if (NULL == pMyPool) {
pMyPool = new MyPool();
printf("======>Creating a new pool object.\n");
}
return reinterpret_cast<T*>(pMyPool->GetNext());
}
//__p is not permitted to be a null pointer
void deallocate(pointer __p, size_type __n) {
pMyPool->Free(reinterpret_cast<void *>(__p));
}
size_type max_size() const throw() {
return size_t(-1)/sizeof(T);
}
void construct(pointer __p, const T& __val) {
printf("+++++++ %08x %s.\n", __p, typeid(T).name());
::new(__p) T(__val);
}
void destroy(pointer __p) {
printf("-+-+-+- %08x.\n", __p);
__p->~T();
}
};
template<typename T>
inline bool operator==(const MyPoolAlloc<T>&, const MyPoolAlloc<T>&) {
return true;
}
template<typename T>
inline bool operator!=(const MyPoolAlloc<T>&, const MyPoolAlloc<T>&) {
return false;
}
template<typename T>
MyPool* MyPoolAlloc<T>::pMyPool = NULL;
int main(int argc, char *argv[]) {
std::map<int, int, std::less<int>, MyPoolAlloc<std::pair<const int,int> > > m;
//random insertions in the map
m.insert(std::pair<int,int>(1,2));
m[5] = 7;
m[8] = 11;
printf("======>End of map insertions.\n");
return 0;
}
Bu programın çıktısı: çıktı gösterinin
-------Alloc--CONSTRUCTOR--------bffcdaa6 St4pairIKiiE Construct T Alloc from X Alloc--bffcda77 St13_Rb_tree_nodeISt4pairIKiiEE St4pairIKiiE Copy Constructor ---------------bffcdad8 St13_Rb_tree_nodeISt4pairIKiiEE Destructor ---------------------bffcda77 St13_Rb_tree_nodeISt4pairIKiiEE Destructor ---------------------bffcdaa6 St4pairIKiiE ======>Creating a new pool object. Construct T Alloc from X Alloc--bffcd9df St4pairIKiiE St13_Rb_tree_nodeISt4pairIKiiEE +++++++ 0985d028 St4pairIKiiE. Destructor ---------------------bffcd9df St4pairIKiiE Construct T Alloc from X Alloc--bffcd95f St4pairIKiiE St13_Rb_tree_nodeISt4pairIKiiEE +++++++ 0985d048 St4pairIKiiE. Destructor ---------------------bffcd95f St4pairIKiiE Construct T Alloc from X Alloc--bffcd95f St4pairIKiiE St13_Rb_tree_nodeISt4pairIKiiEE +++++++ 0985d068 St4pairIKiiE. Destructor ---------------------bffcd95f St4pairIKiiE ======>End of map insertions. Construct T Alloc from X Alloc--bffcda23 St4pairIKiiE St13_Rb_tree_nodeISt4pairIKiiEE -+-+-+- 0985d068. Destructor ---------------------bffcda23 St4pairIKiiE Construct T Alloc from X Alloc--bffcda43 St4pairIKiiE St13_Rb_tree_nodeISt4pairIKiiEE -+-+-+- 0985d048. Destructor ---------------------bffcda43 St4pairIKiiE Construct T Alloc from X Alloc--bffcda43 St4pairIKiiE St13_Rb_tree_nodeISt4pairIKiiEE -+-+-+- 0985d028. Destructor ---------------------bffcda43 St4pairIKiiE Destructor ---------------------bffcdad8 St13_Rb_tree_nodeISt4pairIKiiEE
Son iki sütun olduğunu std::pair<const int, int>
için bir ayırıcı, haritaya her yerleştirildiğinde her zaman oluşturulur. Bu neden gerekli? Bunu bastırmanın bir yolu var mı?
Teşekkürler!
Düzenleme: Bu kod g ++ sürüm 4.1.2 ile x86 makinede test edilmiştir. Eğer bir 64-bit makinede çalıştırmak istiyorsanız, en azından return malloc(24)
hattını değiştirmeniz gerekecektir. return malloc(48)
olarak değiştirilmelidir.
Yukarıdaki çıktıların her göründüğü zaman bunu yapmak kesinlikle yasaktır. STL/C++ bu şekilde yapması gereken içsel bir neden var mı? Eğer değilse, o zaman onu bastırmak için uygulamayı nasıl değiştirirsiniz? –
C++ 03'te, bir uygulayıcının vatansız olduğunu (boş) varsaydığına dair bir uygulamaya izin verilir. Bu şekilde, bir kopya oluşturmak neredeyse ücretsizdir. Durumunuzda, kopya oluşturucu ve atama operatörü dahili işaretçiyi kopyalamanız ve her seferinde yeni bir Havuz oluşturmamanız mümkün olabilir. –
@Bo - Sorunun konusu kopyalayıcı değil! Bunun yerine St13_Rb_tree_nodeISt4pairIKiiEE için bir ayırıcıdan St4pairIKiiE için bir ayırıcı oluşturan kurucu. –