Форум программистов, компьютерный форум CyberForum.ru

allocator своя версия - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 1, средняя оценка - 5.00
Droll
0 / 0 / 0
Регистрация: 07.09.2012
Сообщений: 48
02.06.2013, 19:01     allocator своя версия #1
Доброго времени суток.
Мне нужно написать class allocator на подобии стандартного. Он должен содержать следующие методы:
Method void* allocate (size_t n)
Default: returns malloc (n*sizeof(T))
Method void deallocate (void* pointer)
Default: free(pointer)
Method void construct ( void* p, const T& value)
new(p) T(value);
Method void destroy (T* p)
p->~T();

Я понимаю, что allocate строит память и не вызывается конструктор. Мне не совсем понятно должны ли быть какие-то поля в классе? И если не сложно, напишите (или укажите где можно найти) пример написания подобного allocatora.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.06.2013, 19:01     allocator своя версия
Посмотрите здесь:

std::allocator C++
C++ std::allocator
allocator std::map C++
Своя версия функции strcmp() C++
allocator C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
03.06.2013, 11:09     allocator своя версия #2
Вполне достаточно будет этого.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template<typename T>
class allocator : public std::allocator<T>
{
public:
   typedef std::allocator<T> base;
 
   void* allocate(typename base::size_type n, const void* = 0)
   {
      return malloc(n * sizeof(T));
   }
   void deallocate(void* p, typename base::size_type)
   {
      free(p);
   }
   void construct(void* p, const T& value)
   {
      new (p) T(value);
   }
   void destruct(T* p)
   {
      p->~T();
   }
};
Но это не будет работать со стандартными контейнерами, т.к. allocate возвращает void*.
Droll
0 / 0 / 0
Регистрация: 07.09.2012
Сообщений: 48
03.06.2013, 11:19  [ТС]     allocator своя версия #3
Спасибо за ответ. А что нужно сделать, чтоб работало со стандартными контейнерами?
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
03.06.2013, 11:23     allocator своя версия #4
Droll, Вовращать T*. Т.е.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template<typename T>
class allocator : public std::allocator<T>
{
public:
   typedef std::allocator<T> base;
 
   typename base::pointer allocate(typename base::size_type n, const void* = 0)
   {
      return static_cast<typename base::pointer>(malloc(n * sizeof(T)));
   }
   void deallocate(void* p, typename base::size_type)
   {
      free(p);
   }
   void construct(void* p, const T& value)
   {
      new (p) T(value);
   }
   void destruct(T* p)
   {
      p->~T();
   }
};
Droll
0 / 0 / 0
Регистрация: 07.09.2012
Сообщений: 48
03.06.2013, 11:31  [ТС]     allocator своя версия #5
я так и думал. а можете объяснить почему не работает со стандартными контейнерами? если не сложно.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
03.06.2013, 11:46     allocator своя версия #6
Droll, В С++ запрещено неявное преобразование от void* к T*, т.е. такой код не скомпилируется
C++
1
2
3
4
5
6
#include <cstdlib>
 
int main()
{
   int* p = malloc(sizeof(int));
}
Поэтому нужно добавлять явное преобразование.

C++
1
2
3
4
5
6
#include <cstdlib>
 
int main()
{
   int* p = static_cast<int*>(malloc(sizeof(int)));
}
Контейнеры рассчитывают на то, что allocate будет возвращать
C++
1
allocator::pointer
, потому не делают явных кастов.

Добавлено через 11 минут
Ну и в + без наследования от аллокатора, ежели вдруг оно не нужно.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <cstdlib>
#include <memory>
#include <vector>
 
template<typename T>
class allocator
{
public:
   typedef T value_type;
   typedef T* pointer;
   typedef const T* const_pointer;
   typedef T& reference;
   typedef const T& const_reference;
   typedef size_t size_type;
   typedef ptrdiff_t difference_type;
 
   template<typename U>
   struct rebind
   {
      typedef allocator<T> other;
   };
 
   allocator() {}
   allocator(const allocator&) {}
   template<typename U>
   allocator(const allocator<T>&) {}
 
   pointer allocate(size_type n, const void* = 0)
   {
      return static_cast<pointer>(malloc(n * sizeof(T)));
   }
   void deallocate(pointer p, size_type)
   {
      free(p);
   }
   void construct(pointer p, const T& value)
   {
      new (p) T(value);
   }
   void destruct(pointer p)
   {
      p->~T();
   }
   size_type max_size()
   {
      return std::allocator<T>::max_size();
   }
   pointer address(reference x) const
   {
      return const_cast<pointer>(address(const_cast<const_reference>(x)));
   }
   const_pointer address(const_reference x) const
   {
      return std::allocator<T>().address(x);
   }
};
 
template<typename T>
bool operator == (const allocator<T>&, const allocator<T>&)
{
   return true;
}
 
template<typename T>
bool operator != (const allocator<T>& lhs, const allocator<T>& rhs)
{
   return !(lhs == rhs);
}
 
int main()
{
   std::vector<int, allocator<int> > vector;
   vector.push_back(1);
}
Droll
0 / 0 / 0
Регистрация: 07.09.2012
Сообщений: 48
03.06.2013, 12:53  [ТС]     allocator своя версия #7
Спасибо большое!
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
03.06.2013, 13:12     allocator своя версия #8
ForEveR, кстати, пользуясь случаем хотел спросить: если не смотреть на требование ТС
Цитата Сообщение от Droll Посмотреть сообщение
Default: returns malloc (n*sizeof(T))
есть ли смысл использовать глобальный operator new взамен malloc?
В VS2010 например в итоге всё равно вызывается malloc. А в самом днище упираемся в HeapAlloc.
Как в других реализациях, есть ли гдe new не на базе malloc?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.06.2013, 13:23     allocator своя версия
Еще ссылки по теме:

C++ Распределитель памяти идентичный std::allocator. Непонятные синтаксис и концепция std::allocator::construct
Std::allocator<wchar_t>>' to 'LPCWSTR' C++
Vector allocator SQLite C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
03.06.2013, 13:23     allocator своя версия #9
Tulosba, Не знаю, не интересовался честно говоря особо.
Default behavior:
— Executes a loop: Within the loop, the function first attempts to allocate the requested storage. Whether
the attempt involves a call to the Standard C library function malloc is unspecified.

— Returns a pointer to the allocated storage if the attempt is successful. Otherwise, if the last argument to
set_new_handler() was a null pointer, throw bad_alloc.
— Otherwise, the function calls the current new_handler (18.4.2.2). If the called function returns, the loop
repeats.
— The loop terminates when an attempt to allocate the requested storage is successful or when a called
new_handler function does not return.
У clang (libc++) такое:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
__attribute__((__weak__, __visibility__("default")))
void *
operator new(std::size_t size)
#if !__has_feature(cxx_noexcept)
    throw(std::bad_alloc)
#endif
{
    if (size == 0)
        size = 1;
    void* p;
    while ((p = ::malloc(size)) == 0)
    {
        // If malloc fails and there is a new_handler,
        // call it to try free up memory.
        std::new_handler nh = std::get_new_handler();
        if (nh)
            nh();
        else
#ifndef _LIBCPP_NO_EXCEPTIONS
            throw std::bad_alloc();
#else
            break;
#endif
    }
    return p;
}
 
__attribute__((__weak__, __visibility__("default")))
void
operator delete(void* ptr) _NOEXCEPT
{
    if (ptr)
        ::free(ptr);
}
Ну и в libstdc++

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
_GLIBCXX_WEAK_DEFINITION void *
operator new (std::size_t sz) _GLIBCXX_THROW (std::bad_alloc)
{
  void *p;
 
  /* malloc (0) is unpredictable; avoid it.  */
  if (sz == 0)
    sz = 1;
  p = (void *) malloc (sz);
  while (p == 0)
    {
      new_handler handler = __new_handler;
      if (! handler)
    _GLIBCXX_THROW_OR_ABORT(bad_alloc());
      handler ();
      p = (void *) malloc (sz);
    }
 
  return p;
}
Yandex
Объявления
03.06.2013, 13:23     allocator своя версия
Ответ Создать тему
Опции темы

Текущее время: 17:10. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru