Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.50/6: Рейтинг темы: голосов - 6, средняя оценка - 4.50
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,631

Свой Allocator

04.12.2024, 17:38. Показов 1294. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте! Пожалуй, подниму тему allocator-ов ещё раз, опять же упражнение из книги Страуструпа в котором он предлагает реализовать свой аллокатор. В главе он приводит пример pool-allocator-а, но с ограничение, он выделяет память только для одного элемента, в упражнении же предлагается создать или расширить тот аллокатор, который автор реализовал, для выделения блоков памяти для нескольких значений. И..., что для этого нужно делать, моё предположение, исходя из того что функция grow() создаёт новый кусок и размечает его в цикле для каждого следующего элемента, то в случае выделения блока под n-элементов нужно изменять grow() что бы начало(head) указывала на начало блока, а поле next указывало на окончание данного блока. Хотя, как тогда будет конструироваться объект, по какому адресу?! Собственно это то что я хотел бы узнать на первом этапе.



Мой аллокатор на базе фиксированного пула призван быстро выделять и освобождать память под один элемент, и именно это делает класс Pool. Расширение данной модели на более общие случаи выделения памяти под несколько объектов или под объекты разных размеров(как того требует rebind) я оставляю в качестве упражнения.
Завершите или реализуйте с самого начала Pool_alloc (§19.4.2) так, чтобы обеспечивались все возможности стандартного аллокатора allocator (§19.4.1) из стандартной библиотеки. Сравните производительности Роol_alloc и allocator, чтобы решить, стоит ли использовать Pool_alloc в вашей системе.
Это то что уже сделано Страуструпом
Pool
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
class Pool
{
    private:
        struct Link
        {
            bool isUse;
            Link* next;
        };
        
        struct Chunk
        {
            enum {size = 8 * 1024 - 16 }; //слегка меньше 8К, чтобы кусок памяти умещал-
            char mem[size];               //ся в 8К для достижения точного вырвнивания
            Chunk* next;
        };
        
        Chunk* chunks;
        const unsigned int esize; 
        Link* head;
        Pool(Pool&); //защита от копирования
        void operator=(Pool&); //защита от копирования
        void grow();  //увеличить пул
        
    public:
        Pool(unsigned int n); 
        ~Pool();
        
        void* alloc(size_t n);     //выделить память под один элемент
        void free(void* b);        //возвращает элемент в пул
};
 
inline void* Pool::alloc()
{
    if(head == 0)
        grow();
    Link* p = head; //вурнуть первый элемент 
    head = p->next;
    return p;
}
 
 
inline std::pair<void*, void*> Pool::alloc(size_t n)
{
    Link* first = head;
    Kink* last  = head;
    while(n--)
    {
        last = last->next;
    }
    head = last->next;
    return std::make_pair(first, last);
}
 
 
 
inline void Pool::free(void* b)
{
    Link* p = static_cast<Link*>(b);
    p->next = head;
    head = p;
}
 
Pool::Pool(unsigned int n):esize(n < sizeof(Link) ? sizeof(Link) : n)
{
    head = 0;
    chunks = 0;
}
 
Pool::~Pool() //освободить все куски (chunks)
{
    Chunk* n = chunks;
    while(n)
    {
        Chunk* p = n;
        n = n->next;
        delete p;
    }
}
 
void Pool::grow()  //выделяет новый 'chunk', организуя его в виде связного списка
{                   //элеметов размерос 'esize'
    Chunk* n = new Chunk;
    n->next = chunk;
    chunk = n;
    
    const int nelem = Chunk::size / esize;
    char* start = n->mem;
    char* last = &start[(nelem - 1) * esize];
    
    for(char* p = start; p < last; p += esize)
    {
        reinterpret_cast<Link*>(p)->next = reinterpret_cast<Link*>(p + esize);
    }
    
    reinterpret_cast<Link*>(last)->next = 0;
    head = reinterpret_cast<Link*>(start);
}



Pool_alloc
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
template<typename T>
    class Pool_alloc
    {
    private:
        static Pool mem; //пул элементов размером sizeof(T)
    public:
        //аналогично стандартному allocator
        typedef T value_type;
        typedef T* pointer;
        typedef T& reference;
        typedef const T* const_pointer;
        typedef const T& const_reference;
        typedef size_t size_type;
        typedef ptrdiff_t difference_type;
 
        Pool_alloc() { }
        Pool_alloc(const Pool_alloc&) { }
        template<typename U>
        Pool_alloc(const Pool_alloc<U>&) { }
 
        pointer allocate(size_type n, void* = 0);
        void deallocate(pointer p, size_type n);
        void construct(pointer p, const_reference val);
        void destroy(pointer p);
        size_type max_size() const
        {
            return (size_type)std::numeric_limits<size_type>::max;
        }
 
        template<typename U>
        struct rebind
        {
            typedef Pool_alloc<U> other;
        };
    };
 
    template<typename T>
    Pool Pool_alloc<T>::mem(sizeof(T));
 
    //template<typename T>
    //Pool_alloc<T>::Pool_alloc() { }
 
    template<typename T>
    typename Pool_alloc<T>::pointer Pool_alloc<T>::allocate(size_type n, void*)
    {
        //if(n == 1)
        return static_cast<pointer>(mem.alloc());
        //...
    }
 
    template<typename T>
    void Pool_alloc<T>::deallocate(pointer p, size_type n)
    {
        //if(n == 1)
        //{
        mem.free(p);
        return;
        //}
        //...
    }
 
    template<typename T>
    void Pool_alloc<T>::construct(pointer p, const_reference val)
    {
        new (static_cast<void*>(p)) T(val);
    }
 
    template<typename T>
    void Pool_alloc<T>::destroy(pointer p)
    {
        (static_cast<T*>(p))->~T();
    }
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
04.12.2024, 17:38
Ответы с готовыми решениями:

Как сделать свой контейнер совместимым с std::allocator?
Как сделать свой контейнер совместимым с std::allocator?

Распределитель памяти идентичный std::allocator. Непонятные синтаксис и концепция std::allocator::construct
Компилятор: MSVC 2010 Exress код моего класса распределяющего память под спойлером #include &lt;stdlib.h&gt; // my memory...

allocator
Здорова! Есть задачка:&quot;Завершите или реализуйте с самого начала Pool_alloc (параграф 19.4.2) так, чтобы обеспечивались все возможности...

8
267 / 199 / 30
Регистрация: 26.11.2022
Сообщений: 866
04.12.2024, 20:48
вам потрениоваться (поиграться) или сделать нормальный аллокатор которым пользоваться можно?
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,631
04.12.2024, 23:59  [ТС]
Цитата Сообщение от Aledveu Посмотреть сообщение
вам потрениоваться (поиграться) или сделать нормальный аллокатор которым пользоваться можно?
Да, потренироваться, по возможности понять, как работает эта "кухня" изнутри.

Добавлено через 52 минуты
Видимо, тут нужно ещё предусмотреть некий флаг сообщающий "менеджеру памяти", используется ли это участок или нет. Например, в структуру Link добавить флаг isUse. Но как различит, что данная ячейка не принадлежит некоему диапазону адресов, что я имею ввиду, допустим я зарезервировал память для vector из этой зарезервированной памяти я использую лишь часть ячеек, соответственно, у остальных флаг isUse == false и вот какой-то контейнер пытается выделить память для себя, его аллокатор обращается к адресам, которые уже зарезервированы для vector, но ещё не используются, что делать, как подобного избежать.

Опять же, ещё одна проблема, а что если я выделил диапазон для контейнера, и конструируя элементы выхожу за границу этого диапазона, нужно ли кидать исключение? И как хранить и, самое главное где, границы этого диапазона.

При resize() может быть фрагментация это тоже нужно учитывать..., пока что море вопросов.

Тогда в класс Pool нужно будет внести изменение, добавить функцию alloc(size_t n); тогда нужно добавить free(void* p, size_t n); для симметрии.
0
267 / 199 / 30
Регистрация: 26.11.2022
Сообщений: 866
05.12.2024, 00:35
тогда надо начать с понимания. Когда нужен свой аллокатор.
Когда у вас есть особые требования к эксплуатации этого аллокатора, которые обычными аллокаторами входящими в состав стандартной библиотеки не решаются.
Например:
1)Скорость работы. Вы пишете сетевой стек сервера многопользовательской игры. вам надо каждому игроку посылать и принимать udp пакеты. размер до 1492 байт (с учётом что часть пользователей может сидеть через pppoe или чего аналогичного). Вам приходится посылать и принимать тысячи таких пакетов в секунду, что-то из этого запоминать и некоторое врмя хранить. Вам надо это делать очень быстро. На помошь приходит pool-allocator. Размер блока фиксированный, а скорость работы - максимальная. Стандарнтый аллокатор не такой быстрый. попробуйте в рандомном порядке делать malloc|free для 20000 блоков в секунду, когда не менее 10000 из них выделено.
2)Работа с внешней памятью. Когда у вас метаданные о выделенных блоках хранятся отдельно от самих блоков, а область памяти внутри которой надо работать заранее определена. Типичный пример - выделение памяти видеоадаптера под модели и текстуры. Стандартный аллокатор такого в принципе не умеет.
3)особые требования по обслуживанию. например как talloc.
4)Требования по выравниванию. возвращаемый участок памяти должен быть выровнян хотябы по 16 байт. иначе при включенной оптимизации будете вываливаться в ОС на каждой SSE инструкции )))

Вот от этих требований и надо отталкиваться.

У вас сейчас каша. pool allocator - как раз специально сделан чтобы максимально быстро "жонглировать" блоками одинакового размера, и не надо из него франкенштейна делать.

Если хотите поиграться - то освойте аллокаторы по порядку.
https://habr.com/ru/articles/505632/
Научитесь их использовать - для чего каждый нужен и паттерны применения.
и надо сразу понимать - в 99% случаев свои аллокаторы бесполезны ))
1
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,631
05.12.2024, 17:12  [ТС]
Цитата Сообщение от Aledveu Посмотреть сообщение
Когда у вас есть особые требования к эксплуатации этого аллокатора, которые обычными аллокаторами входящими в состав стандартной библиотеки не решаются.
На данный момент у меня особых требований к аллокаторам нет, но мало ли возникнет нужда в этом инструменте.

Цитата Сообщение от Aledveu Посмотреть сообщение
У вас сейчас каша. pool allocator - как раз специально сделан чтобы максимально быстро "жонглировать" блоками одинакового размера, и не надо из него франкенштейна делать.
Я описал ход своих мыслей, никакого франкенштейна создавать не собирался), к тому же я не говорил, что я понимаю в этой теме, если бы это было так я бы вопросов не задавал. Есть нюансы, которые мне не ясны и сейчас после прочтения статьи ссылку на которую вы мне дали. Но кое что стало яснее, но не всё.
Почитав про pool-allocator-ы я решил, что нужно подправить класс pool, возможно, что опять мимо, но всё же... Если требуется выделить память для одного элемента, то всё остаётся как прежде, если же требуется выделить память для нескольких элементов(возможно, терминология не верна), то нужно применить следующую функцию alloc и free:
Я их не проверял в работе т.к. это всего лишь идея, с большой вероятностью, неудачная.

alloc(size_t n)
C++
1
2
3
4
5
6
7
8
9
10
inline void* Pool::alloc(size_t n)
{
    //last - последнее значение в данном chunk
    Link* last  = &chanks->mem[((chunk::size / esize) - 1) * esize];
    if((head + n * esize) > last) //если в chunk нет места для всех n-значение, тогда
        grow();                   //выделить новый chunk
    Link* p = head + n * esize;   //сигнализирует о том месте где начинается свободная
    head = p->next;               //память
    return p;
}


free(void*, size_t)
C++
1
2
3
4
5
6
7
8
9
inline void Pool::free(void* b, size_t n)
{
    Link* p = static_cast<Link*>(b);
    Link* e = &p[n * esize];  //e-последний элемент в последовательности элементов, 
                              //память под которую была выделена с помощью alloc(size_t)
    head->next = e->next;     //пытаюсь перенести данную группу элементов в начало 
    p->next = head;           //списка, подобно тому, как это делается для одного
    head = p;                 //элемента.
}



Не по теме:

Цитата Сообщение от Aledveu Посмотреть сообщение
паттерны применения.
А по-русски что ещё за "паттерны".

0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,631
07.12.2024, 16:00  [ТС]
Кликните здесь для просмотра всего текста
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#include <iostream>
#include<limits>
//#include<memory>
 
#include<vector>
#include<list>
#include<iterator>
#include<map>
 
namespace ch19
{
    using std::numeric_limits;
 
    class Pool
    {
    private:
        struct Link
        {
            Link* next;
        };
 
        struct Chunk
        {
            enum { size = 8 * 1024 - 16 };
            char mem[size];
            Chunk* next;
        };
 
        Chunk* chunks;
        const unsigned int esize;
        Link* head;
        Pool(Pool&) = delete; //Защита от копирования
        void operator=(Pool&) = delete; //Защита от копирования
        void grow();
 
    public:
        Pool(unsigned int n);
        ~Pool();
 
        void* alloc(/*size_t n*/);       //выделить память под один элемент
        void free(void* b);  //возвращает элемент в пул
 
        void* alloc(size_t);
        void free(void*, size_t);
    };
 
 
    inline void* Pool::alloc()
    {
        if(head == 0)
            grow();
        Link* p = head; //вурнуть первый элемент
        head = p->next;
        return p;
    }
 
 
    inline void Pool::free(void* b)
    {
        Link* p = static_cast<Link*>(b);
        p->next = head;
        head = p;
    }
    
    //++++++++++++++++++++++++++++++++++++++++++
    inline void* Pool::alloc(size_t n)
    {
        if (head == 0)
            grow();
        Link* p = head;
        Link* q = p;
        while (n--)
        {
            if (q)
                q = q->next;
            else
            {
                grow();
                q = head;
            }
        }
        head = q->next;
        return p;
    }
 
    inline void Pool::free(void* b, size_t n)
    {
        Link* p = static_cast<Link*>(b);
        p->next = head;
        head = p;
    }
    
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    
    Pool::Pool(unsigned int n):esize(n < sizeof(Link) ? sizeof(Link) : n)
    {
        head = 0;
        chunks = 0;
    }
    
    Pool::~Pool() //освободить все куски (chunks)
    {
        Chunk* n = chunks;
        while(n)
        {
            Chunk* p = n;
            n = n->next;
            delete p;
        }
    }
 
    void Pool::grow()
    {
        Chunk* n = new Chunk;
        n->next = chunks;
        chunks = n;
 
        const int nelem = Chunk::size / esize;
        char* start = n->mem;
        char* last = &start[(nelem - 1) * esize];
 
        for(char* p = start; p < last; p += esize)
        {
            reinterpret_cast<Link*>(p)->next = reinterpret_cast<Link*>(p + esize);
        }
 
        reinterpret_cast<Link*>(last)->next = 0;
        head = reinterpret_cast<Link*>(start);
    }
    
 
 
    template<typename T>
    class Pool_alloc
    {
    private:
        static Pool mem; //пул элементов размером sizeof(T)
    public:
        //аналогично стандартному allocator
        typedef T value_type;
        typedef T* pointer;
        typedef T& reference;
        typedef const T* const_pointer;
        typedef const T& const_reference;
        typedef size_t size_type;
        typedef ptrdiff_t difference_type;
 
        Pool_alloc() { }
        Pool_alloc(const Pool_alloc&) { }
        template<typename U>
        Pool_alloc(const Pool_alloc<U>&) { }
 
        pointer allocate(size_type n, void* = 0);
        void deallocate(pointer p, size_type n);
        void construct(pointer p, const_reference val);
        void destroy(pointer p);
        size_type max_size() const
        {
            return (size_type)std::numeric_limits<size_type>::max;
        }
 
        template<typename U>
        struct rebind
        {
            typedef Pool_alloc<U> other;
        };
    };
 
    template<typename T>
    Pool Pool_alloc<T>::mem(sizeof(T));
 
    //template<typename T>
    //Pool_alloc<T>::Pool_alloc() { }
 
    template<typename T>
    typename Pool_alloc<T>::pointer Pool_alloc<T>::allocate(size_type n, void*)
    {
        if(n == 1)
            return static_cast<pointer>(mem.alloc());
        //...
        return static_cast<pointer>(mem.alloc(n));
        
    }
 
    template<typename T>
    void Pool_alloc<T>::deallocate(pointer p, size_type n)
    {
        if(n == 1)
        {
        mem.free(p);
        return;
        }
        //...
        mem.free(p, n);
    }
 
    template<typename T>
    void Pool_alloc<T>::construct(pointer p, const_reference val)
    {
        new (static_cast<void*>(p)) T(val);
    }
 
    template<typename T>
    void Pool_alloc<T>::destroy(pointer p)
    {
        (static_cast<T*>(p))->~T();
    }
}
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,631
08.12.2024, 17:42  [ТС]
Linear_alloc
Кликните здесь для просмотра всего текста
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
75
76
77
78
79
#include <iostream>
#include<utility>
 
#include<algorithm>
#include<iterator>
#include<vector>
 
using namespace std;
 
namespace ch18
{
    template<typename T, size_t _N = 1024>
class Linear_alloc
{
    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;
 
        Linear_alloc():used(0), N(_N) { start = mem; }
        Linear_alloc(const Linear_alloc&) { }
 
        template<typename U>
        Linear_alloc(const Linear_alloc<U>&) { }
        ~Linear_alloc() { start = nullptr; used = 0; }
 
        pointer allocate(size_t n, void* = 0)
        {
            if((used >= N) || ((start + used + sizeof(T) * n) >= (mem + N)))
                return 0;
            pointer ptr  = reinterpret_cast<pointer>((mem + used) /*+ sizeof(T) * n */);
 
 
            used += sizeof(T) * n;
            std::cout << "Allocated memory: " << ((mem + used) - start) / sizeof(T) << std::endl;
            return ptr;
        }
 
        void deallocate(pointer p, size_t n)
        {
            used = 0;
            //N = 0;
            //start = nullptr;
        }
 
        //void construct(const T& val)
        template</*typename U,*/ typename... Args>
        void construct(T* p, Args&&... args)
        {
            std::cout << "The a memory block that will be construct: '" << p << "'" << std::endl;
            ::new(static_cast<void*>(p)) T(forward<Args>(args)...);
        }
        //void destroy(const T& val);
        //template<typename U>
        void destroy(T* p)
        {
            std::cout << "The a memory block that destroying: '" << p << "'" << std::endl;
            p->~T();
        }
 
        template<typename U>
        struct rebind
        {
            typedef Linear_alloc<U> other;
        };
 
    private:
        static unsigned char mem[_N];
        unsigned char* start;
        size_t used, N;
};
template<typename T, size_t _N>
unsigned char Linear_alloc<T, _N>::mem[_N];
 
}
0
 Аватар для Liss29
225 / 39 / 4
Регистрация: 18.11.2012
Сообщений: 1,631
09.12.2024, 14:35  [ТС]
Stack_alloc
Кликните здесь для просмотра всего текста
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
namespace ch19
{
    template<typename T, size_t _N = 1024>
class Stack_alloc
{
    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;
 
        Stack_alloc():header(nullptr), top(0), N(_N) { }
        Stack_alloc(const Stack_alloc&) { }
 
        template<typename U>
        Stack_alloc(const Stack_alloc<U>&) { }
        ~Stack_alloc()
        {
            top = 0;
            Header* t = header;
            while(t)
            {
                Header* del = t;
                t = t->next;
                delete del;
            }
        }
 
        pointer allocate(size_t n)
        {
            if((top >= N) || ((mem + top + n) >= (mem + N)))
                return 0;
 
            pointer ptr  = reinterpret_cast<pointer>(mem + top);
 
            Header* h = new Header;
            h->sizeOfBlock = n;
            h->next = header;
            header = h;
 
            //new(static_cast<void*>(ptr)) Header(h);
            //ptr += sizeof(Header);
 
 
            top += sizeof(T) * n;
            return ptr;
        }
 
        void deallocate(T* p, size_t n)
        {
            Header* h = header;
            if(!h)
                return;
            header = h->next;
            top -= h->sizeOfBlock * sizeof(T);
            delete h;
        }
 
        //void construct(const T& val)
        template<typename... Args>
        void construct(T* p, Args&&... args)
        {
            ::new(static_cast<void*>(p)) T(std::forward<Args>(args)...);
        }
        //void destroy(const T& val);
        //template<typename U>
        void destroy(T* p)
        {
            p->~T();
        }
 
        template<typename U>
        struct rebind
        {
            typedef Stack_alloc<U> other;
        };
 
    private:
        struct Header { size_t sizeOfBlock; Header* next; };
        Header* header;
 
        static unsigned char mem[_N];
        //unsigned char* start, *end;
        size_t top, N;
};
 
template<typename T, size_t _N>
unsigned char Stack_alloc<T, _N>::mem[_N];
}
0
267 / 199 / 30
Регистрация: 26.11.2022
Сообщений: 866
09.12.2024, 16:12
а теперь расскажите как вы их будете применять - с примерами.
ибо это самое интересное.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
09.12.2024, 16:12
Помогаю со студенческими работами здесь

Allocator и shared_ptr
Прокомментируйте пожалуйста. Есть ли смысл и вообще возможность оформлять зарезервированную память allocator-ом в shared_ptr? Или это...

std::allocator
я не смог найти хорошего описания роботы с аллокатором, так что спрашиваю у тех, кто с ним работал std::allocator::allocate (size_type...

std::allocator
Здравствуйте! Подскажите почему возникает ошибка сегментирования: using std::cout; using std::endl; int main() { ...

Ошибка с allocator
Приветствую. Пользуюсь Dev-C++. При выполнении кода, ошибка, что на скрине. #include &lt;iostream&gt; int main() { ...

Указатели и allocator
Здравствуйте. Не так давно начал изучать с++. Возник такой вопрос. Допустим у нас есть массив указателей на что-то. shared_ptr&lt;int&gt;,...


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

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru