Есть ли распределитель С++, который уважает переопределенное новое/удаление?

Я реализую операцию клонирования выделения ресурсов для массива типа T. В простой реализации используется new T[sz], за которой следует вызов std::copy из источника в новый массив. Он дважды просматривает память.

Я хотел бы выделить необработанную память, а затем использовать std::uninitialized_copy, поэтому я просто занимаюсь памятью один раз по соображениям производительности. Я знаю, как это сделать, когда используется пользовательский распределитель (Allocator.allocate, а затем std::uninitialized_copy), и я знаю, как это сделать, используя std::allocator (который использует ::operator new после lib.allocator.members в разделе 20.4.1.1 спецификация). Моя забота заключается в том, что подход <<26 > кажется неправильным для типов T, где T::operator new определено. Я знаю, что могу обнаружить такую ​​ситуацию, используя Boost.TypeTraits 'has_new_operator.

Существует ли простой, стандартизованный способ выделения и затем инициализации необработанной памяти таким образом, который будет уважать переопределенное новое (и делает ли это передачу памяти только один раз)? Если нет, использует SFINAE для отправки между реализацией, использующей std::allocator, а другой с использованием переопределенного оператора new, как представляется, разумным? FWIW, grepping through Boost не показывает такого использования признака has_new_operator.

Спасибо, Риз

Ответ 1

Кажется, это невозможно. Только operator new[] знает, как сохранить размер массива (если T имеет деструктор) по определенному пути реализации (operator delete[] затем использует эту информацию). Поэтому нет переносного способа хранения этой информации без нового выражения (и без конструкторов вызывающих элементов).

Ответ 2

попробуйте установить новое место.

    typedef std::string T;
    T src[5];
    char* p = new char[sizeof(T)* 5];
    T* dest = (T*)p;
    for(int i = 0;i < 5; ++i)
    {       
        new(dest + i) T(src[i]); //placement new
    }