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
BTW използвате 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