Как стать автором
Обновить
0
0

Пользователь

Отправить сообщение
к сожалению, не глобальные аллокаторы с состоянием это дикий гемор(
например если в аллокаторе не указан propagate_on_container_swap как true_type
alloc<int> a1{...};
std::vector<int, alloc<int>> vec1{a1};
alloc<int> a2{...};
std::vector<int, alloc<int>> vec2{a2};
std::swap(a1, a2); // UB

и отдельный гемор если нужно передавать аллокатор «в глубь» контейнера
std::vector<std::set<int>>

c 17го стандарта лучше смотреть в сторону en.cppreference.com/w/cpp/memory/polymorphic_allocator
уменьшение числа маленьких аллокаций при использовании make_shared уже существенный плюс
для примера уйдем в другую крайность, множество маленьких аллокаций и ни одного weak_ptr
#include <iostream>
#include <chrono>
#include <list>

template<class T, class F>
auto test(F&& create)
{
  std::list<std::shared_ptr<T>> set;
  auto max = std::numeric_limits<size_t>::max();
  for (size_t count = 0; count < max - 1; ++count)
  {
    try
    {
      set.emplace_back(create(count));
    }
    catch (const std::bad_alloc&)
    {
      return count;
    }
  }

  return max;
}

int main(int argc, char *argv[])
{
  using namespace std::chrono;
  using type = int;
  if (argc == 1)
  {
    auto start = steady_clock::now();
    auto val = test<type>([](auto val) { return std::make_shared<type>(val); });
    auto end = steady_clock::now();
    std::cout << "make_shared | count: " << val << ", time: " << duration_cast<milliseconds>(end - start).count() << "msc\n";
  }
  else
  {
    auto start = steady_clock::now();
    auto val = test<type>([](auto val) { return new type(val); });
    auto end = steady_clock::now();
    std::cout << "new | count: " << val << ", time: " << duration_cast<milliseconds>(end - start).count() << "msc\n";
  }
}

вариант с make_shared делает 2 аллокации на элемент, вместо трех, позволяя эффективнее использовать память
на моем компе x86 вариант с make_shared размещает на треть элементов больше)
PS. тестить лучше в разные запуски
...
template<class T, class FAllocator = FastMemPoolNull >
struct FastMemPoolAllocator : public std::allocator<T>  
...
std::unordered_map<int,  int>  umap2(1024, std::hash<int>(), std::equal_to<int>(),  FastMemPoolAllocator<std::pair<const int,  int>>());

так лучше не делать, в c++17 не просто так задеприкейтили половину функций в std::allocator
в конструкторе unordered_map происхоит усечение до std::allocator, в котором нет ни одной виртуальной функции
см.
en.cppreference.com/w/cpp/memory/allocator_traits
если уж хочется от чего-то унаследоваться см.
en.cppreference.com/w/cpp/memory/memory_resource
en.cppreference.com/w/cpp/memory/polymorphic_allocator
template<typename Function>
static auto make(Function&& func)
{
  return[func = std::forward<Function>(func)](auto&&... args)
  {
    std::cout << "Do something" << std::endl;
    return std::invoke(func, std::forward<decltype(args)>(args)...);
  };
}

можно не переименовать, т.к. func слева от = в захвате относится к неймспейсу лямбды
не стоит в лямбду захватывать ссылку

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность