Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 9, средняя оценка - 4.89
VoltDeMar
16 / 16 / 0
Регистрация: 05.06.2012
Сообщений: 1,015
#1

Malloc vs new - C++

08.07.2015, 14:54. Просмотров 1308. Ответов 33
Метки нет (Все метки)

Здравствуйте.

Вникаю в ручное управление памятью. Абзац из книги "C++ для профессионалов" не совпадает с моим представлением использования объектов. Тут написано:

C++
1
2
Foo* myFoo = {Foo*}malloc(sizeof(Foo));
Foo* myOtherFoo = new Foo();
После выполнения этих строк кода как переменная myFoo, так и переменная myOtherFoo будут указывать на области памяти в "куче", которые имею достаточный размер для хранения объекта Foo. К членам данных и методам объекта Foo можно получить доступ с помощью обоих указателей. Различие между ними состоит в том, что объект Foo, адресуемый указателем myFoo, не является, по сути, объектом, поскольку он не был построен.

Из других источников прочел что malloc не вызывает конструктор.

Но как это удается получить доступ к членам данных и методам объекта которого не существует. И образуется в памяти после выполнения malloc ?

Или это значит что после выделения памяти при помощи malloc нужно вручную вызывать конструктор?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.07.2015, 14:54
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Malloc vs new (C++):

new на malloc - C++
Измените выделение памяти на C - malloc,и почему у меня не открывает текстовый файл? #include "stdafx.h" #include <string.h> ...

new vs malloc - C++
Чем new безопаснее(или лучше?) malloc?

new, malloc, - C++
Добрый день. При роботе с дин. памяттю в конец выделяемой памяти добавляеться какойто бред, чтото топа "<<<ЮЮЮээээ". Почему так...

malloc в С++ - C++
Подскажите пожалуйста как в данной программе выделить динамическую память с помощью malloc для объекта #include <iostream> ...

malloc() - C++
4to takoe malloc(), za4em nam ono nujno? pomogite=)))))))

malloc vs new - C++
Доброго времени суток. Когда я для выделения памяти пользовался malloc/calloc и освобождал с помощью free, у меня вылетала ошибка: ...

Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
MansMI
1159 / 951 / 246
Регистрация: 08.01.2012
Сообщений: 3,487
08.07.2015, 15:00 #2
все доступно, но если конструктор рандомно или еще как заполняет поля, то у *myFoo они левые, не помню чистит ли память malloc, если так то нулевые
Croessmah
Модератор
Эксперт CЭксперт С++
13133 / 7396 / 828
Регистрация: 27.09.2012
Сообщений: 18,227
Записей в блоге: 3
Завершенные тесты: 1
08.07.2015, 15:10 #3
Цитата Сообщение от VoltDeMar Посмотреть сообщение
Из других источников прочел что malloc не вызывает конструктор.
он даже про них не знает. Это функция из библиотеки C, а не C++
VoltDeMar
16 / 16 / 0
Регистрация: 05.06.2012
Сообщений: 1,015
08.07.2015, 15:12  [ТС] #4
Цитата Сообщение от MansMI Посмотреть сообщение
все доступно, но если конструктор рандомно или еще как заполняет поля, то у *myFoo они левые, не помню чистит ли память malloc, если так то нулевые
о каком конструкторе речь, malloc вызывает какие то конструкторы? Как происходит доступ к методам класса без объекта, что расположено в памяти?
MansMI
1159 / 951 / 246
Регистрация: 08.01.2012
Сообщений: 3,487
08.07.2015, 15:31 #5
malloc не вызывает какие то конструкторы
DrOffset
7090 / 4231 / 950
Регистрация: 30.01.2014
Сообщений: 7,006
08.07.2015, 15:35 #6
Цитата Сообщение от VoltDeMar Посмотреть сообщение
malloc вызывает какие то конструкторы?
Нет.
Цитата Сообщение от VoltDeMar Посмотреть сообщение
Как происходит доступ к методам класса без объекта, что расположено в памяти?
По сути, функция класса может быть реализована так:
C++
1
<тип возвращаемого значения> Foo_method(Foo* this, <аргументы>);
Т.е. компилятору все равно (если дело не касается виртуальных вызовов), что память, которая отведена под объект, не инициализирована. Он сгенерирует код, где указатель на эту память передается в эту функцию первым скрытым параметром при вызове и все.
Другое дело, что код, который должен работать внутри функции-члена, может зависеть от состояния объекта, которое задается конструктором. Иными словами программа будет работать, но некорректно.

Вот это из цитаты:
Цитата Сообщение от VoltDeMar
Различие между ними состоит в том, что объект Foo, адресуемый указателем myFoo, не является, по сути, объектом, поскольку он не был построен.
И вот это
Цитата Сообщение от VoltDeMar
прочел что malloc не вызывает конструктор.
Об одном и том же. "Объект не был построен" == "не был вызван конструктор".

Вот тебе код для размышления:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <new>
#include <iostream>
 
class A { 
public:
    A() : v(10) {}
 
    void foo() { std::cout << v << std::endl;  }
private:
    int v;
};
 
int main()
{
    char memory[sizeof(A)]; // Пока что опустим детали насчет выравнивания
 
    A * p = (A*)memory;
 
    p->foo();
 
    ::new(p) A();
 
    p->foo();
};
Tulosba
:)
Эксперт С++
4393 / 3236 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
08.07.2015, 15:38 #7
VoltDeMar, malloc выделяет сырую память, указанного размера.
new выделяет память, а потом вызывает конструктор типа.
Если тип является POD (plain old data), то различий в вызовах new и malloc практически нет.
VoltDeMar
16 / 16 / 0
Регистрация: 05.06.2012
Сообщений: 1,015
08.07.2015, 16:47  [ТС] #8
Цитата Сообщение от DrOffset Посмотреть сообщение
По сути, функция класса может быть реализована так:
Хочется узнать как это реализуется в реальности.
Цитата Сообщение от DrOffset Посмотреть сообщение
Вот тебе код для размышления:
Что я должен понять из этого кода?

Добавлено через 9 минут
на сplusplus.com написано: The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.

Как происходит поэтапно доступ к членам класса?
DrOffset
7090 / 4231 / 950
Регистрация: 30.01.2014
Сообщений: 7,006
08.07.2015, 17:08 #9
Цитата Сообщение от VoltDeMar Посмотреть сообщение
Хочется узнать как это реализуется в реальности.
Как показал, так и реализуется.

Цитата Сообщение от VoltDeMar Посмотреть сообщение
Что я должен понять из этого кода?
То, что любой блок памяти можно представить как любой объект и работать с ним так, как будто бы он там есть.
С этой точки зрения все равно есть ли в объекте конкретные значения или там мусор лежит. Главное, что есть память.

Цитата Сообщение от VoltDeMar Посмотреть сообщение
Как происходит поэтапно доступ к членам класса?
Выше показал. Вот есть класс А:
C++
1
2
3
4
5
6
class A {
public:
    int v;
    
    A() : v(10) {}
};
Добавим ему функцию foo:
C++
1
2
3
4
5
6
7
8
9
10
class A {
public:
    int v;
 
    A() : v(10) {}
 
    void foo() {
         printf("value: %d\n", v);
    }
};
Что в реальности будет сделано? Компилятором будет создана такая функция:
C++
1
2
3
    void foo(A * this) {
         printf("value: %d\n", this->v);
    }
Теперь создадим объект через new. Выражение new включает выделенеи памяти и инициализацию объекта. Выделение памяти делается посредством operator new (который можно перегружать), будет выделена память sizeof(A). А он, в свою очередь, может быть реализован как обычный malloc. Итого:
C++
1
A * p = (A*)malloc(sizeof(A));
Теперь проводим инициализацию (вызываем конструктор):
C++
1
::new(p) A(); // здесь v задается значение 10
Здесь будет вызван конструктор для памяти, которую выделил malloc.
Затем сделаем вызов функции foo, который по сути является вот чем:
C++
1
foo(p); // p->foo();
Тут все понятно?
Теперь выкинем вызов конструктора из этой цепочки. Что изменилось? У v значение не 10, а какое-то случайное, которые было в памяти до ее использования в аллокации. И printf в foo выведет это число. Больше ничего не поменялось.

Никакие структуры данных, отвечающие на строение классов в рантайме не сохраняются (статически типизированный, компилируемый язык). Есть только память, регистры и смещения в памяти, которые генерирует компилятор, строя машинный код. Если мы в коде написали, что, вот этот блок памяти - имеет тип A, то и код будет генерироваться таким образом, чтобы отвечать принятым для А (размеры данных, смещения полей от начала блока, отступы для выравнивания и т.д.) соглашениям (это называется ABI).
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
6447 / 3094 / 306
Регистрация: 04.12.2011
Сообщений: 8,567
Записей в блоге: 4
08.07.2015, 18:38 #10
DrOffset, похоже что ТС почти понял, что методы не хранятся в объекте и вот-вот поймет.
Ну то есть на неинициализированном объекте можно вызвать метод (он как код принадлежит типу), а данные в этом методе будут мусором и результат непредсказуем. Если я понимаю правильно.
Evg
Эксперт CАвтор FAQ
17621 / 5845 / 375
Регистрация: 30.03.2009
Сообщений: 16,118
Записей в блоге: 26
08.07.2015, 20:24 #11
Цитата Сообщение от VoltDeMar Посмотреть сообщение
Из других источников прочел что malloc не вызывает конструктор.
Но как это удается получить доступ к членам данных и методам объекта которого не существует. И образуется в памяти после выполнения malloc ?
Ты допускаешь стандартную ошибку, полагая, что конструктор занимается выделением памяти. Это не так. Конструктор занимается исключительно инициализацией полей в объекте, для которого память уже выделена. Просто new делает сразу две вещи - выделяет память (по сути malloc) и запускает конструктор. Подробнее можешь почитать тут: http://www.cyberforum.ru/blogs/18334/blog103.html
-=ЮрА=-
Заблокирован
Автор FAQ
08.07.2015, 20:50 #12
malloc как и new выделяет память, отличие в том что new кидает exception(собственно поэтому маллок нельзя использовать в плюсовых программах). Выше на прау постов человек пытался подстроить к алоцирвоанию placement new это отдельная тема и для простой структуры или типа разницы в аллоцировании хоть будет нью хоть маллок не будет никакой.

Добавлено через 12 минут
Вот конкретно пергрузка аллоцирования (всё будет работать но код будет не кашерным с точки зрения исключений)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
using namespace std;
 
void* operator new(size_t size) {
    return malloc(size);
}
 
void operator delete(void* ptr) {
  free(ptr);
}
 
class cTest{
    protected :
    size_t v;
    public:
    cTest(){
        v = 100;
    }
    size_t get_v(){return v;}
};
 
int main(){
    cTest * ptr = new cTest();
    cout<<ptr->get_v()<<endl;
    return 0;
}
http://ideone.com/lfevfL
И честное слово мне уже на форуме надоел бред мол new отличается от malloc (кроме ексепшина ничем, а если вы пишете под ВИН то поглядите на СРТ дебаг память - удивитесь вообще).

Не по теме:

Есть new есть placement new не мешайте понятния чёрт побери.

Kastaneda
Форумчанин
Эксперт С++
4652 / 2860 / 228
Регистрация: 12.12.2009
Сообщений: 7,268
Записей в блоге: 2
Завершенные тесты: 1
08.07.2015, 21:07 #13
Вот это еще можно почитать. Писал правда 2 года назад, сейчас бы по-другому написал, но переписывать лень

Добавлено через 36 секунд
Цитата Сообщение от Kastaneda Посмотреть сообщение
сейчас бы по-другому написал
В статье все правильно, просто сейчас бы стилистически по-другому материал преподнес.
DrOffset
7090 / 4231 / 950
Регистрация: 30.01.2014
Сообщений: 7,006
08.07.2015, 21:48 #14
Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
Выше на прау постов человек пытался подстроить к алоцирвоанию placement new
Я ничего не пытался. Считай, что это был псевдокод. Напрямую к placement new здесь не имеет смысла обращаться. Просто в С++ нет синтаксиса для отдельного вызова конструктора для заданной памяти, кроме как с использованием placement new.
В общем здесь это не существенно. ТСу непонятно как можно вызвать метод для неинициализированного объекта, а пример показывал что разницы между инициализированной памятью объекта и неинициализированной нет, с точки зрения вызова невиртуального метода.
IGPIGP
Комп_Оратор)
Эксперт по математике/физике
6447 / 3094 / 306
Регистрация: 04.12.2011
Сообщений: 8,567
Записей в блоге: 4
08.07.2015, 22:50 #15
Kastaneda, а разве между функцией и выражением есть разница? Даже функция возвращающая значение типа void является выражением. Конструктор не укладывается в определение функции. Метод может ничего не возвращать (конструктор/деструктор) то есть не быть выражением.
Есть глобальная операторная функция new и операторная же функция-член. Если последняя определена (перегружен глобальный оператор) то к глобальному можно обратиться с помощью оператора разрешения ::
А перегрузить-то можно всяко же? Можно сделать что бы он не только конструктор не вызывал, но и память не выделял. Печатал на экране "бла-бла-бла" и всё. Это ничего не доказывает. Вот пример, где параметр задан, тоже чтобы компилятор скушал, но и память выделяется и конструктор запускается. Хотя это конечно не обязательно. Перегрузить можно всё что перегружается. Остальное вопрос совести и доброй воли.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream> 
using namespace std;
 
struct A{
int a;
A():a(0){}
A(int a_):a(a_){}
 
void * operator new(size_t){
cout<<"operator new"<<endl;
return ::new A;
}
 
};
int main()
{
A* p = new A(10);
cout<<p->a;
cout<<endl;
    system("pause");
return 0;
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
08.07.2015, 22:50
Привет! Вот еще темы с ответами:

New и malloc - C++
Если смотреть на выделение памяти для арифметических типов уступает ли функций new malloc'у в скорости? Если да, то насколько это критично?

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

calloc vs malloc - C++
Объясните,пжлста,чем отличается malloc oт calloc?

Функция Malloc - C++
Помогите изучить функцию Malloc что она делает или дайте учебник где она описана! Начальный курс давно закончил, хорошо разбираюсь в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
08.07.2015, 22:50
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru