Какие алгоритмы в библиотеке стандартных алгоритмов выделяются и есть ли способ указать, как происходит это распределение?

Я бы хотел больше использовать стандартные алгоритмы, но предъявляю довольно жесткие требования к управлению распределением памяти.

Есть ли исчерпывающий список, какие алгоритмы выделить?
Кроме того, есть ли способ контролировать, как происходит это распределение? Единственный вариант, переопределяющий глобальный новый? Это на самом деле работает, если ссылки статически? До C++17 казалось, что все выделения проходили через std::get_teorary_buffer() для выделения памяти, но это кажется устаревшим в C++17. Что заменяет это?

3 ответа

Решение

Похоже, что единственный способ получить контроль над распределением - это переопределить глобальное новое. Смотрите здесь, раздел "Глобальные замены"

http://en.cppreference.com/w/cpp/memory/new/operator_new

Так как это работает во время соединения, это означает, что каждый dll должен будет связать модуль перевода с переопределенным глобальным new / delete. Как именно это соответствует какой-либо конкретной стратегии распределения, вероятно, выходит за рамки этого вопроса.

Другие ответы здесь указывают, какие алгоритмы пытаются использовать временные.

stable_partition, stable_sort и inplace_merge

AFAIR ни один из стандартных алгоритмов не выделяет память, если:

  1. ваш пользовательский тип выделяет память во время копирования или перемещения, или
  2. ваш выходной итератор выделяет память во время присваивания значения - например std::back_insert_iterator<>

Исправление:

Его используют следующие алгоритмы:

  • stable_partition
  • inplace_merge
  • stable_sort

Кажется, что реальность такова, что реализация libstdC++ просто пытается выделить буфер, используя T::operator newи делит размер выделения пополам, если new call возвращает ноль, пока размер выделения не станет равным нулю.

  template<typename _Tp>
     pair<_Tp*, ptrdiff_t>
     __get_temporary_buffer(ptrdiff_t __len, _Tp*)
     {
       const ptrdiff_t __max = numeric_limits<ptrdiff_t>::max() / sizeof(_Tp);
       if (__len > __max)
     __len = __max;

       while (__len > 0) 
     {
       _Tp* __tmp = static_cast<_Tp*>(::operator new(__len * sizeof(_Tp), 
                             nothrow));
       if (__tmp != 0)
         return pair<_Tp*, ptrdiff_t>(__tmp, __len);
       __len /= 2;
     }
       return pair<_Tp*, ptrdiff_t>(static_cast<_Tp*>(0), 0);
     }

источник: https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.0/memory-source.html

Оказывается, что эта функция является спорной, так как Александр Степанов, оригинальный автор СТЛ, написал это как реализацию заполнителя, оставляя документацию, она никогда не должна идти в производство.

Излишне говорить, что это было, и с тех пор было в каждом порту STL.

Для непараллельных алгоритмов stable_partition, stable_sort, а также inplace_merge это три, которые определенно попытаются получить дополнительную память, прибегая к менее эффективному алгоритму, если он не может этого сделать. Как именно они пытаются получить память, не уточняется.

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

Другие вопросы по тегам