2014-01-13 4 views
4

Я прочитал в книге на C++, что malloc() & free() являются личными функциями и, следовательно, находятся вне контроля компилятора.Как справиться с управлением компилятором при распределении и освобождении памяти на C++?

Однако, если у вас есть возможность оператору выполнить комбинированный акт инициализации динамического распределения памяти & (new) и другой оператор для выполнения комбинированного акта ВЫМЫТЬ & отпуская хранения (delete), компилятор может все еще гарантировать, что конструкторы & деструкторы будут вызываться для всех объектов.

Итак, я хочу знать, как это выполняется компилятором? Любой пример или демонстрационная версия будут указаны.

Заранее спасибо.

+3

Следует отметить, что malloc() и free() не являются «предпочтительным» способом выделения памяти на C++. Они в основном предназначены для простой поддержки C. C++ вы обычно используете новые и удаляете. – seand

ответ

4

mallocФункция возвращает кусок смежной памяти, вот и все. То, как вы набираете текст и используете его (для ваших объектов), является вашей проблемой.

В то время как оператор new возвращает объекты, выделенные в память. Хотя оба возвращают указатель, в конце вы получаете построенные объекты, а не необработанную память в C++. Здесь фокус переходит от низкоуровневой обработки памяти к обработке объектов, с которой возникает безопасность типа. Вот почему new не возвращает void*.

Кроме того, если вы заметили, что в первом случае C это функция, которая выполняет выделение, то есть сам язык не имеет понятия выделения объектов или памяти. В то время как в C++ new является оператором, и, следовательно, язык по сути понимает, что означает динамическое создание объектов. Компилятор реализует то, что задает язык, и, таким образом, он может помечать ошибку при ее обнаружении.

Примером может быть:

int *ptr = malloc(sizeof(char) * 4); 

Здесь программист принимает целое число имеет размер , в то время как это может быть правдой в своей платформе, это, безусловно, не верно для всех платформ. Также концептуально char и int - это разные типы, но несоответствие типов игнорируется компилятором C. Все, что он делает, вызывает функцию malloc и присваивает адрес, который он возвращает, ptr. Это домен заканчивается там, программисту нужно использовать (или злоупотреблять?) Выделенную память. Это не ошибка или слабость в части компилятора, поскольку языковой стандарт не дает больше полномочий компилятору для обеспечения большего количества.

В то время как в C++

int *ptr = new char[4]; 

будет помечен как ошибка; правильный способ сделать это будет int *ptr = new int;, где типы совпадают. C++ более строг, позволяя меньшую свободу в местах, где ошибки являются общими, там, приводя к более чистым кодам. Тип безопасности, возможно, является самой большой функцией безопасности на языке C++.Тип casting имеет уродливый синтаксис по той же причине: они показывают слабые стороны дизайна. С более строгим языком компилятор может обеспечить дополнительные ограничения для разработчика (поскольку люди более подвержены ошибкам, в большинстве случаев это хорошо работает).

2

Компилятор фактически не «помогает» выделять и освобождать память; ваш код должен явно это сделать. Язык C++ обеспечивает детерминированное выполнение кода, когда поток оставляет область (деструкторы). Это, в свою очередь, часто используется для освобождения памяти, выделенной кучей.

0

новый и удалить ключевые слова в C++.

C++ компиляторы будут генерировать скрытые коды для вас, чтобы иметь дело с распределением памяти/деаллокацией.

Например,

struct Test() { } 
Test *a = new Test(); 

компилятор может сделать что-то вроде этого, (следующий псевдокод)

Test *a = (Test *)malloc(sizeof(Test)); 
if (a == nullptr) { throw std::bad_alloc; } 
try 
{ 
    a.Test(); //call constructor 
} 
catch (...) 
{ 
    //constructor exception, free the memory first, then re-throw 
    free(a); 
    throw; 
} 

Если для массива, все будет сложнее,

struct Test() { } 
Test *a = new Test[10]; 

Компилятор может сделать что-то вроде этого:

Test *a = (Test *)malloc(sizeof(Test) * 10); 
if (a == nullptr) { throw std::bad_alloc; } 
int i; 
try 
{ 
    for (i = 0; i < 10, i++) 
     a[i].Test(); //call constructor 
} 
catch (...) 
{ 
    //call destructor for all constructed objects 
    for (int j = 0; j < i; j++) 
     a[j].~Test(); 

    free(a); 
    throw; 
} 

Подобные логические работы для удаления.

Смежные вопросы