LINUX.ORG.RU

использование new(void*, size_t)


0

0

вопрос такой, коректно ли следующее использование, нет ли в нем опасности, и верно ли я понял что оператор new(void*, size_t) ваяет обьект на уже выделенную (до его вызова) память?


class BaseM{
const string str;
public:
BaseM(const char* str_) : str(str_) {
cout << " create: " << str.c_str() << endl;
}
void show_str() const {
cout << str.c_str() << endl;
}
~BaseM(){
cout << " delete " << str.c_str() << endl;
}

};

int main()
{

char* ptr_arena = new char[sizeof(BaseM) * 3];
cout << "ptr_arena: " << ((void*) ptr_arena) << endl; ///***

BaseM* ptr_1 = new (ptr_arena) BaseM("string #1");
BaseM* ptr_2 = new (ptr_arena + sizeof(BaseM)) BaseM("string #2");
BaseM* ptr_3 = new (ptr_arena + sizeof(BaseM) * 2) BaseM("string #3");

for(int i = 0; i < 3; ++i){
cout << " sdress: " << (reinterpret_cast<BaseM*>(ptr_arena) + i) << ", ";
(reinterpret_cast<BaseM*>(ptr_arena) + i)->show_str();
}

ptr_3 = new (ptr_arena + sizeof(BaseM) * 2) BaseM("string #3777");
for(int i = 0, j = 0; i < 3 ; ++i){
reinterpret_cast<BaseM*>(ptr_arena + j)->show_str();
j += sizeof(BaseM);
}
return 0;
}

А деструкторы кто будет вызывать?

Legioner ★★★★★
()

такая форма оператора new не вызывает выделения памяти (на то он и placement new, размещающий new), как следствие - единственный (кажется) случай в C++, когда есть необходимость явного вызова деструкторов (память очищать на данном логическом уровне как правило не надо, однако объект-то разрушить стоит - RAII никто не отменял)

jtootf ★★★★★
()

ИМХО new выделяет память, выровненную только для одного типа (в твоём случае - char). И полученный блок памяти может не подойти по выравниванию для BaseM. В результате на некоторых архитектурах процессоров код не будет работать или будет работать неправильно. Так что лучше использовать malloc, который выдаёт адрес, гарантированно пригодный для размещения любых типов, либо написать какую-нибудь обёртку над new char[N].

Хотя лучше по этому поводу почитать стандарт, я могу и ошиьаться...

Ну и плюс то что сказали выше.

Deleted
()
Ответ на: комментарий от Deleted

> ИМХО new выделяет память, выровненную только для одного типа (в твоём случае - char).

Нет, new выделяет память, гарантированно корректно выровненную для любого типа.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

> Нет, new выделяет память, гарантированно корректно выровненную для любого типа.

только malloc и realloc гарантированно дают память выровненную для любого типа.

new по дефолту вызывает operator new(size_t):

void* operator new(std::size_t size) throw(std::bad_alloc);

-1- Effects: The allocation function (basic.stc.dynamic.allocation) called by a new-expression (expr.new) to allocate size bytes of storage suitably aligned to represent any object of that size.

-2- Replaceable: a C++ program may define a function with this function signature that displaces the default version defined by the C++ Standard library.

то есть выровненную не для любого типа, а для любого типа этого размера. По счастливой случайности, там указан размер sizeof(BaseM)*3. Если бы было написано sizeof(BaseM)*3 + 1, то уже была бы ошибка.

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

> только malloc и realloc гарантированно дают память выровненную для любого типа.

Да, перепутал. Спасибо за исправление.

Legioner ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.