1

Тема: Чому об'єкт не можна створювати за допомогою malloc?

Привіт всім,
бачив на одному сайті присвяченому С++, що створювати об'єкти класу через malloc не можна.

struct X {
    int a, b;
};

int main() {
    X *p = (X*)malloc(sizeof(X));
    p->a = 1;
    p->b = 2;
    free(p);
}

І що код вище є не правильним в С++ і, що так можна писати лише в С, але не в С++. Але чому так не можна робити в С++?

Подякували: wander1

2

Re: Чому об'єкт не можна створювати за допомогою malloc?

What everyone has told you, new combines the call to get memory from the freestore with a call to the object's constructor. Malloc only does half of that.

Подякували: koala, leofun012

3

Re: Чому об'єкт не можна створювати за допомогою malloc?

У загальному випадку, об'єкт може вимагати ініціалізуючих дій (виклики конструкторів), що виконуються при використанні new, тоді як malloc просто виділяє блок пам'яті й повертає вказівник на нього без жодних додаткових дій. Якщо це примітивна структура без елементів ООП, ця різниця може бути некритичною, але використання в ній полів, що мають об'єктний тип, вже вимагає ініціалізації.

Подякували: mimik, leofun012

4

Re: Чому об'єкт не можна створювати за допомогою malloc?

І що це означає?

Подякували: wander1

5

Re: Чому об'єкт не можна створювати за допомогою malloc?

Бо ви заплутуєте ситуацію.
Ніхто не забороняє використовувати malloc/calloc/realloc/free у C++, навіть більше, "під капотом" вони активно використовуються. Але new - це не лише виклик malloc, але й виклик конструктора, як правильно написав ur_naz; крім того, new може для певних класів викликати не malloc, а щось інше. Тому, якщо вам насправді потрібно використовувати malloc у програмі на C++ - на здоров'я, але відповідальність за виклик free тоді - виключно на вас, і Боже вас збав викликати delete для об'єкта, пам'ять для якого виділена через calloc (або навпаки - зробити free, коли об'єкт був створений через new). А якщо не хочете плутатися - просто користуйтеся new/delete і не чіпайте низькорівневі засоби для роботи з пам'яттю без потреби.

Подякували: mimik, leofun012

6 Востаннє редагувалося wander (28.02.2020 17:22:06)

Re: Чому об'єкт не можна створювати за допомогою malloc?

mimik написав:

Але чому так не можна робити в С++?

Бо, згідно стандарту С++ такий код викликає невизначену поведінку (undefined behavior, UB).

http://eel.is/c++draft/intro.object#1 написав:

An object is created by a definition, by a new-expression, when implicitly changing the active member of a union, or when a temporary object is created.

mimik написав:

так можна писати лише в С, але не в С++

В С++ так не можна робити, через основну відмінність між С та С++, яка полягає у тому, що в С++ є таке поняття як продовжуваність життя об'єктів (та взагалі життя об'єкту, the lifetime of an object). Життя об'єкту в С++ розпочинається, коли конструктор завершив свою роботу, та закінчується коли розпочався виклик деструктора. Власне, а malloc не викликає ніяких конструкторів, відповідно об'єкт ніколи не розпочинав своє існування, то що ви в нього хочете?

mimik написав:

І що це означає?

Це означає, що до С++20 ви так не могли робити, а з С++20 можете, і можете забути половину з того, що я писав та використовувати malloc, і ніяких UB не буде :)

Подякували: koala, mimik, leofun013

7 Востаннє редагувалося wander (28.02.2020 23:29:01)

Re: Чому об'єкт не можна створювати за допомогою malloc?

mimik, взагалі ваш код, який використовує malloc можна вилікувати, якщо у вас ще не С++20 :)
malloc - вже виділив для вас необхідний кусок пам'яті, єдине чого вам бракує, то це виклику конструктора, який би вдихнув життя в ваш об'єкт. Це вміє робити placement new, який на відміну від свого брата звичайного new, не виділяє ніякої динамічної пам'яті, а лише, так сказати, розміщує/конструює у вже виділеному куску пам'яті необхідний вам об'єкт. Виглядало б це так:

struct X {
    int a, b;
};

int main() {
    X *p = (X*)malloc(sizeof(X));
    new (p) X; // більше не UB
    p->a = 1;
    p->b = 2;
    free(p);
}
Подякували: mimik, P.Y., sensei, leofun01, /KIT\, ReAl6

8

Re: Чому об'єкт не можна створювати за допомогою malloc?

wander написав:

єдине чого вам бракує, то це виклику конструктора, який би вдихнув життя в ваш об'єкт. Це вміє робити placement new

І коли мене тягне по++-ти для дрібних мікроконтролерів, я це часом використовую, щоб виділяти пам'ять статично під різні об'єкти, які використовуються ексклюзивно (або залежно від конфігурації, або строго по черзі).

Якось так

Подякували: leofun011

9

Re: Чому об'єкт не можна створювати за допомогою malloc?

wander написав:

Це означає, що до С++20 ви так не могли робити, а з С++20 можете, і можете забути половину з того, що я писав та використовувати malloc, і ніяких UB не буде :)

А що там у 20-му?
Я й попередні новини не читав :-)

10

Re: Чому об'єкт не можна створювати за допомогою malloc?

ReAl написав:

А що там у 20-му?

Ой, та багато всього. Чогось доброго подобавляли, чогось не дуже, кхм...
Конкретно по темі, можна ознайомитися з даним пропозалом.

Подякували: leofun011

11 Востаннє редагувалося ExPy (29.07.2020 23:31:53)

Re: Чому об'єкт не можна створювати за допомогою malloc?

Можна перегрузити (чи як там) malloc на new
I все можна буде.
Я , правда, роблю навпаки, на new видiляю память через heapalloc.

12

Re: Чому об'єкт не можна створювати за допомогою malloc?

ExPy написав:

Можна перегрузити (чи як там) malloc на new
I все можна буде.
Я , правда, роблю навпаки, на new видiляю память через heapalloc.

*FACEPALM*

Подякували: koala, leofun012

13

Re: Чому об'єкт не можна створювати за допомогою malloc?

треба команду yanealloc використовувати

14

Re: Чому об'єкт не можна створювати за допомогою malloc?

ExPy, і яке це має відношення до теми?

Подякували: leofun01, mimik2