malloc() для массива объектов структуры

Пытаюсь понять, как управлять памятью в C++ в стиле C:

struct aaa{
public:
    int a ;
    int b ;
    std::string c ;
};

int asize =5;

int main() 
{
    aaa * a;
    a = static_cast<aaa *>(malloc(sizeof(aaa) * asize));
    for (int i;i<asize;i++)
    {
        a[i] =  aaa(); //crash
    }
    a[0].c = "ddd";
    a[1].c = "ccc";
    a[2].c = "eee";
}

Сбой программы при создании объекта структуры в первом сегменте памяти. Что я делаю неправильно (кроме C в C++)?


person vico    schedule 23.01.2018    source источник
comment
Проблема в том, что вы используете malloc. Не используйте malloc, используйте new.   -  person molbdnilo    schedule 23.01.2018
comment
std::malloc не вызывает конструктор типа. Допустимо, если конструктор типа, который вы хотите создать, тривиален, а ваш — нет из-за c.   -  person Rakete1111    schedule 23.01.2018
comment
но я вызываю конструктор вручную в for(...)   -  person vico    schedule 23.01.2018
comment
@vico Вы создаете aaa(), а затем перемещаете-назначаете его на a[i]. Правильный способ вызвать конструктор хранилища для a[i] — использовать new (&a[i]) aaa() или new (a + i) aaa().   -  person jotik    schedule 23.01.2018
comment
Используйте std::vector.   -  person    schedule 23.01.2018
comment
зачем ты звонил malloc? Все объяснения того, как использовать malloc и заставить работать конструкторы, не имеют значения, если у вас нет веских (редких) причин для использования malloc.   -  person pm100    schedule 23.01.2018
comment
Кстати, вы используете new[] для выделения массива   -  person pm100    schedule 23.01.2018
comment
@jotik But a[i] = new (a + i) aaa() выдает ошибку error: no match for ‘operator=’ (operand types are ‘aaa’ and ‘aaa*’)   -  person vico    schedule 24.01.2018
comment
@vico Не выполняйте задание, а только новое размещение. Весь оператор должен быть new (a + i) aaa();. Задание не нужно. Он просто создает объект aaa по адресу a + i.   -  person jotik    schedule 24.01.2018


Ответы (1)


Вы не можете копировать в объект, для которого вы не вызывали конструктор:

a[i] =  aaa(); //crash

Вы можете сделать так:

new (a + i) aaa();
a[i] =  aaa(); //no crash

Класс имеет нетривиальный конструктор по умолчанию, если хотя бы один из его нестатических членов имеет нетривиальный конструктор по умолчанию. В вашем случае std::string c не имеет тривиального конструктора по умолчанию, поэтому malloc в этом случае недостаточно.

person Yola    schedule 23.01.2018