Как Стандарт C++ регламентирует правильное использование malloc()?

Скажите, пожалуйста, для каких типов в C++ достаточно использования malloc(), вместо new()?

Я спрашиваю, потому что, согласно правилам C++, если мы выделяем память (при помощи malloc() и родственных функций), то это не означает, что в выделенной памяти существует объект.

Например:

Object*const object = reinterpret_cast<Object*const>(malloc(sizeof(Object)));

У меня есть подозрения, что приведенный выше код может нарушать Правила Строгих Псевдонимов (Strict Aliasing Rules), потому что никакого объекта типа Object по указанному адресу не существует, там просто существует кусок памяти, размер и выравнивание которого достаточны для размещения там объекта типа Object. У меня даже есть сомнения в том, что запись в object полученного адреса является законной операцией.

И я подозреваю, что мы должны сделать так:

void*const mem = malloc(sizeof(Object));
Object*const object = new(mem) Object();

Почему? Потому что в C есть концепция действующего типа. Мы можем записать в сырую память что-то и таким образом изменить действующий тип. Но в C++ такой концепции нет, но есть концепция динамического типа. Очевидно, что динамический тип устанавливается функциями динамического разрешения, в число которых malloc() (и родственные ей функции) не входят.

Скажите пожалуйста, прав ли я, и если нет, то в чем я ошибаюсь?


Ответы (3 шт):

Автор решения: KoVadim

По правилам языка, только new создает объект. Поэтому, если Вы создаете через вызов malloc вручную, компилятор законно имеет право считать, что объект не был создан и делать оптимизации/предположения на основании этого. Но все так часто использовали подобный паттерн, что ни один компилятор не делал такого. Более того, даже сейчас есть предложения считать, что malloc "создает объект" (объект как сущность, но вызывать конструктор он конечно не будет).

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

→ Ссылка
Автор решения: gbg

Опытные специалисты считают такое использование malloc ошибочным. Я со своей стороны рекомендую не использовать malloc/free в коде на C++ - легко перемешать их, и, к примеру, удалить память, выделенную malloc при помощи delete, что приведет к UB с печальными последствиями.

→ Ссылка
Автор решения: Тарас Атавин

Два условия:

  1. отсутствие конструкторов и декструктора;
  2. допустимость всех возможных значений.
    И стандарт здесь не причём, это простая логика: malloc отличается тем, что не вызывает конструктор вообще никак не иницаилизирует выделенную память, то есть в ней будет мусор, а парная к ней free не вызывает деструктор. А вот стандарт как раз разрешает выделять всегда и как угодно, но требует после любого выделения памяти без вызова конструкторов вызывать placement new, а перед освобождением явно вызывать деструктор.
→ Ссылка