-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Возможность realloc #28
Comments
Олег Ляттэ, 6 декабря 2016, 1:14 Victor Dyachenko, 6 декабря 2016, 15:42 Victor Dyachenko, 6 декабря 2016, 15:42 Не готов пока предложить конкретный интерфейс, но идея такая. Распределитель памяти должен либо возвращать указатель на расширенный блок памяти, либо просто неудачу (например Victor Dyachenko, 6 декабря 2016, 15:54 yndx-antoshkka, 7 декабря 2016, 12:55 Основная идея: добавить "обратную связь", чтобы контейнер мог узнавать у аллокатора сколько памяти в действительности он выделил. Другие подходы скорее всего не будут работать на современных имплементациях malloc/new, которые как правило аллоцируют блоки одного из предопределённых размеров и просто не могут расширять проаллоцированный блок за пределы этого предопределённого размера. Другие подходы могут так же негативно повлиять на вычислительную сложность работы с контейнером, на что комитет не пойдёт. Victor Dyachenko, 7 декабря 2016, 13:39 P.S. Через вашу ссылку нашёл более близкое предложение: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3495.htm yndx-antoshkka, 7 декабря 2016, 16:42
Если вы создадите вектор на 2049 char и будете постепенно вызывать push_back ещё 2047 раз, то realloc вызовется 2047 раз. Это может дать серьёзное замедление производительности. Либо разработчик контейнера будет пытаться вызвать realloc для в два раза большего объема памяти, и realloc всегда будет возвращать новый блок. if (capacity == size) {
ptr = reallocate (size * 2);
capacity = size * 2;
} В этом случае, мы ничего не достигли, это аналогично вызовам new+move+delete. При этом придётся переместить логику new+move range+delete внутрь Сравните со случаем, когда аллокатор просто будет честно возвращать размер блока:
Если вы создадите вектор на 2049 char и будете вызывать push_back ещё 2047 раз, то мы даже не зайдем внутрь if. Это будет ощутимо быстрее. При этом, на современных имплементациях libc, оба подхода будут выдавать абсолютно одинаковые результаты. Более того, используя подход "вытаскиваем информацию из аллокатора" можно будет написать функцию realloc, работающую с любыми аллокаторами. А вот из функции realloc не получится сделать нечто, достающее истинный размер блока из аллокатора. Victor Dyachenko, 7 декабря 2016, 17:36
Почему это? Что мешает расширить на то же значение, на которое расширяет текущая реализация? Почему именно 1? yndx-antoshkka, 7 декабря 2016, 19:56
Вариант расширения в 2 раза рассмотрен сразу после первого примера, в том же сообщении. Victor Dyachenko, 7 декабря 2016, 22:05
Вот тут не понял, из чего следует такое поведение?
Не нужно этого делать. Логика перемещения остаётся в контейнере! Ещё раз, аллокатор мы только просим расширить существующий блок. И он либо удовлетворяет наш запрос, либо сообщает, что он этого сделать не может. Похоже, надо пример написать, чтобы меня поняли правильно. void push_back(T v)
{
if(size() == capacity())
{
size_t new_capacity = ...;
if(extend(space_ptr_, new_capacity))
{
// удалось расширить
capacity_ = new_capacity;
}
else
{
// расширить не получается выделяем новый блок; перемещаем данныеж
}
}
space_ptr_[size_++] = v;
} P.S. Ничто не мешает добавить сюда возможность аллокатору сообщать, сколько он реально выделил и использовать это значение. Это ОРТОГОНАЛЬНОЕ предложение, можно делать и то и другое. yndx-antoshkka, 13 декабря 2016, 15:03 Victor Dyachenko, 14 декабря 2016, 16:09 Текст лучше напишу на русском для начала (с английским у меня не очень...) Дальше, наверное, удобнее будет общаться через e-mail. На какой адрес прислать набросок? Victor Dyachenko, 1 февраля 2017, 14:13 yndx-antoshkka, 1 февраля 2017, 15:34
Дедлайн для новых предложений - ближайшая пятница (оффициально дедлайн 2017-02-06, но было скинуто предупреждение что дедлайн скорее всего наступит в пятницу). Лично я бы рекомендовал не торопиться (скорее всего на ближайшем заседании обсуждать будут в основном только С++17), дождаться отклика на std-proposals и скрестить вашу идею с идеей Jonathan Wakely. Victor Dyachenko, 1 февраля 2017, 15:55
Да, подождём откликов с std-proposals. Сам Jonathan Wakely добавлен список рассылки. Еще попросил бы Вас присылать замечания по использованию английского, если что бросилось в глаза. С ним у меня туго... :-[ yndx-antoshkka, 1 февраля 2017, 21:52
Дмитрий, 1 апреля 2017, 12:54
Ватенов Артем, 24 февраля 2018, 18:10 |
Перенос предложения: голоса +8, -1
Aвтор идеи: h4tred
В текущем виде, если нужно увеличить размер массива, мы вынуждены сначала аллоцировать новый, после чего делать копию/перемещение существующих элементов и освобождать память. Это объяснимо и применимо для типов у которых есть нетривиальные конструкторы копирования/перемещения, но не является оптимильным для простых типов.
Примерный вид может быть таким:
new_ptr = new (old_ptr) Foo[new_size];
Сигнатура для оператора new, может быть такой:
тег нужен, что бы не конфликтовать с существующей сигнатурой для placement new.
Предложенный синтаксис в текущем виде применим для placement new, но может вызывать ряд проблем:
Если кто-то осторожно работает с placement new для массивов, возможна поломка обратной совместимости. Что бы избежать возможно:
Данных механизм применим только для памяти выделенной при помощи new[].
Поддержка со стороны языка нужна, что бы можно было отличить тип элемента массива и правильно принять решение: делать
realloc
или вызыватьnew[]+move/copy+delete[]
.The text was updated successfully, but these errors were encountered: