2013-10-13 5 views
-2

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

На самом деле я получил этот псевдо C++ код:

unsigned long __stdcall MyFunction() 
    { 
    //Do some code that will take a while to complete... 

     { 
      MY_BIG_STRUCT mbStruct = {}; 
      mbStruct.a = "a"; 
      [...]; 
      UseMyStructData(&mbStruct); 
     } 

    //Do some code that will take a while to complete... 

    return EXIT_SUCCESS; 
} 

Так что мой вопрос: На JAVA с помощью этих блоков кода внутри скобок {} маркируют как «свободный» эти переменные GC освободить их, даже если функция не закончил его выполнение. Итак, на C++ это работает одинаково? Или бесполезно использовать {}, если у меня нет инструкции блока (например, если, в то время как, переключатель и т. Д.)?

С уважением,

Afonso Lage.

+1

Как можно работать «так же» - C++ имеет совершенно другую модель объекта и памяти от Java. Этот вопрос даже не имеет смысла. –

+0

@Walter Почему? У меня есть рабочая функция обратного вызова, которая использует ее на VS2012 ... –

+0

@Walter - __stdcall - это особенность Windows. Он определяет, очищает ли вызываемая или вызывающая функция стек. – edtheprogrammerguy

ответ

2

В неконфигурированном C++ отсутствует GC. Деструктор для mbStruct будет вызываться в конце скобки }, однако, поскольку он является переменной в стеке (в отличие от кучи с new). {} создает область видимости, которая вызывает вызов деструктора в закрывающей скобке. Деструктор гарантированно работает, даже если исключение выбрасывается из функции.

Кроме того, C++ использует «детерминированное разрушение», что означает, что вам гарантировано, что деструктор будет выполняться синхронно (при закрытии }), в отличие от системы с GC, где объект удаляется по усмотрению Менеджер памяти GC.

0

Работает аналогично в C++. Ваш MY_BIG_STRUCT будет выпущен в конце блока.

1

Автоматические переменные, выделенные на стек, будут освобождены. Это не то же самое, что сборщик мусора в Java, поскольку его автоматическое распределение стека, а не распределение кучи. Разумеется, для вас это будет выглядеть одинаково.

Если выделить что-то из кучи (с помощью new/malloc) - вы должны де-выделить себя (с помощью delete/free). Используйте unique_ptr или shared_ptr.

1

В C++ отсутствует GC. Однако сборщики мусора имеют дело только с динамической памятью. То есть с new или malloc(). Автоматические переменные уничтожаются, когда их объем выходит. mbStruct - это автоматическая переменная, поэтому она будет уничтожена, когда она выйдет за рамки.

Кроме того, вам не нужны явные области { }, если вы не хотите мелкозернистого управления. Также обратите внимание, что область заканчивается еще до закрытия }. Например:

void foo() 
{ 
    SomeClass someObj; 
    if (some_condition) { 
     return; 
    } 
} 

someObj собирается быть уничтожен, даже если some_condition верно и return выполняется; оставляя область действия, имеет тот же эффект, что и ее окончание.

Вы должны позаботиться о том, чтобы не держать указатели (или ссылки) на переменные, которые вышли за рамки.Например, это будет взорвать:

void foo() 
{ 
    SomeClass* someObj_ptr; 

    { 
     SomeClass someObj; 
     someObj_ptr = &someObj; 
    } 
    someObj_ptr->function(); // Mistake: someObj no longer exists. 
} 

После того, как внутренняя сфера заканчивается, someObj был разрушен, но до сих пор someObj_ptr относится к нему. Вызов function() на нем (при условии, что SomeClass имеет такую ​​функцию-член) является ошибкой. Учтите, что компилятор не способен поймать эту ошибку. Вы должны знать об этом и никогда не указывать указатели или ссылки на переменные, которые вышли за рамки. В отличие от Java, в C++ переменные не засчитываются и не сохраняются в живых, если есть ссылки на них. Если переменная выходит за пределы области видимости, она исчезает, независимо от того, ссылаются ли на нее другие переменные.

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