Использование malloc вместо new и вызов конструктора копирования при создании объекта

Я хотел попробовать масштабируемый_аллокатор TBB, но был сбит с толку, когда мне пришлось заменить часть моего кода. Вот как выполняется распределение с помощью распределителя:

SomeClass* s = scalable_allocator<SomeClass>().allocate( sizeof(SomeClass) );

РЕДАКТИРОВАТЬ: то, что показано выше, не соответствует тому, как распределение выполняется с помощью масштабируемого_аллокатора. Как ymett правильно упомянул, распределение делается так:

int numberOfObjectsToAllocateFor = 1;
SomeClass* s = scalable_allocator<SomeClass>().allocate( numberOfObjectsToAllocateFor );
scalable_allocator<SomeClass>().construct( s, SomeClass());
scalable_allocator<SomeClass>().destroy(s);
scalable_allocator<SomeClass>().deallocate(s, numberOfObjectsToAllocateFor);

Это очень похоже на использование malloc:

SomeClass* s = (SomeClass*) malloc (sizeof(SomeClass));

Это код, который я хотел заменить:

SomeClass* SomeClass::Clone() const
{
   return new SomeClass(*this);
}//Clone

Итак, попробовал программу:

#include<iostream>
#include<cstdlib>
using namespace std;

class S
{
        public:
        int i;
        S() {cout<<"constructed"<<endl;}
        ~S() {cout<<"destructed"<<endl;}
        S(const S& s):i(s.i) {}
};

int main()
{
        S* s = (S*) malloc(sizeof(S));
        s = (S*) S();//this is obviously wrong
        free(s);
}

и здесь я обнаружил, что вызов malloc не создает экземпляр объекта (ранее я никогда не использовал malloc). Поэтому, прежде чем выяснять, как передать *this копировщику, я хотел бы знать, как создать экземпляр объекта при работе с malloc.


person Nav    schedule 10.02.2011    source источник
comment
stackoverflow.com/questions/222557/cs-placement-new   -  person etarion    schedule 10.02.2011
comment
Почему бы вам не переопределить operator new ни для интересующего вас класса, ни только для глобального?   -  person sharptooth    schedule 10.02.2011
comment
@sharptooth: Это хорошая идея, но пока я просто проверяю, действительно ли масштабируемый_аллокатор помогает избежать конкуренции за кучу. Переопределение new обязательно пригодится, если тесты пройдут успешно. Спасибо :)   -  person Nav    schedule 10.02.2011
comment
Если распределитель соответствует стандарту, он должен иметь метод построения и уничтожения: cplusplus.com/reference/std/memory/allocator/construct   -  person visitor    schedule 10.02.2011
comment
Переопределение operator new() намного быстрее и надежнее — вы просто делаете это и перекомпилируете и смотрите, поможет ли это, вам не нужно менять вызывающий код — это сразу везде вступит в силу.   -  person sharptooth    schedule 10.02.2011


Ответы (3)


Вам нужно будет использовать placement new после получения необработанной памяти от malloc.

void* mem = malloc(sizeof(S));
S* s = new (mem) S(); //this is the so called "placement new"

Когда вы закончите с объектом, вы должны явно вызвать его деструктор.

s->~S();
free(mem);
person manneorama    schedule 10.02.2011
comment
Спасибо. Казалось нелогичным использовать «новое», когда вся цель использования масштабируемого_аллокатора TBB заключалась в замене нового. Но я предполагаю, что это другое, потому что используется новое размещение. - person Nav; 10.02.2011

Используйте новое размещение

#include <memory>
//...
int main()
{
        S* s = (S*) malloc(sizeof(S));
        s = new (s) S();//placement new
        //...
        s->~S();
        free(s);
}
person KitsuneYMG    schedule 10.02.2011

Параметр allocate() — это количество объектов, а не их размер в байтах. Затем вы вызываете функцию construct() распределителя для создания объекта.

scalable_allocator<SomeClass> sa;
SomeClass* s = sa.allocate(1);
sa.construct(s, SomeClass());
// ...
sa.destroy(s);
sa.deallocate(s);

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

std::vector<SomeClass, scalable_allocator<SomeClass>> v;
person ymett    schedule 10.02.2011
comment
Я не согласен. конструкция() используется для размещения новой функциональности. Я взял синтаксис allocate() из одного из примеров, представленных в TBB. Но так как вы опубликовали это, я заинтригован. Я проверю и вернусь к вам. Спасибо :) - person Nav; 10.02.2011
comment
О боже! Ты прав! Миллион благодарностей за то, что поправили меня! Печально, что на этом веб-сайте нет возможности проголосовать за ответ более одного раза. Я бы проголосовал сто раз! Один вопрос: в строке sa.construct(s, SomeClass()); , создается ли временный объект SomeClass()? Кроме того, я не понимаю смысла выделять n объектов. Если бы я сделал sa.allocate(2); тогда мне придется построить два объекта, используя sa.construct(s, SomeClass()); ? p.s.: не могли бы вы немного отредактировать свой ответ? SO не позволяет мне голосовать за ваш ответ, говоря, что вам нужно его отредактировать. - person Nav; 10.02.2011
comment
Отредактировал мой вопрос, включив в него исправленную версию кода. Большое спасибо! Вывод моей программы теперь constructed destructed destructed. Первое «уничтожение» происходит сразу после/во время функции build(). Интересно, почему. - person Nav; 11.02.2011