Когда переменные удалены из памяти в C++?

Единственной причиной, которую я использую awk, является авторазделение:

awk '{print $3}' < file.in

Это печатает третье разграниченное пробелом поле в file.in. Это немного легче, чем:

tr -s ' ' < file.in | cut -d' ' -f3
5
задан Rob Kennedy 10 December 2009 в 15:31
поделиться

11 ответов

Локальная переменная temp «помещается» в стек в начале функции и «выталкивается» из стека при выходе из функции.

Вот пример дизассемблирование из неоптимизированной версии:

int addTwo(int num)
{
00411380  push        ebp  
00411381  mov         ebp,esp             //Store current stack pointer
00411383  sub         esp,0CCh            //Reserve space on stack for locals etc
00411389  push        ebx  
0041138A  push        esi  
0041138B  push        edi  
0041138C  lea         edi,[ebp-0CCh] 
00411392  mov         ecx,33h 
00411397  mov         eax,0CCCCCCCCh 
0041139C  rep stos    dword ptr es:[edi] 
    int temp = 2;
0041139E  mov         dword ptr [temp],2 
    num += temp;
004113A5  mov         eax,dword ptr [num] 
004113A8  add         eax,dword ptr [temp] 
004113AB  mov         dword ptr [num],eax 
    return num;
004113AE  mov         eax,dword ptr [num] 
}
004113B1  pop         edi  
004113B2  pop         esi  
004113B3  pop         ebx  
004113B4  mov         esp,ebp                 //Restore stack pointer
004113B6  pop         ebp  
004113B7  ret        

Термины «вытолкнуто» и «вытолкнуто» означают просто аналогию. Как видно из выходных данных сборки, компилятор резервирует всю память для локальных переменных и т.д. за один раз, вычитая подходящее значение из указателя стека.

7
ответ дан 18 December 2019 в 05:15
поделиться

Обычно управление памятью используется в контексте динамической памяти, которая создается

new
malloc

. В нормальном коде C ++ ведет себя как любой другой язык. Если вы создаете переменную или возвращаете ее, она копируется и становится доступной на целевой стороне.

int a = addTwo(3);

получает копию вашего возвращенного значения. Если возвращаемое значение - это оператор копирования класса, вызываемый. Так что, пока вы не работаете с new и malloc, вам не нужно особо заботиться об управлении памятью.

Еще одно важное замечание

void func(std::string abc)
{
  // method gets a copy of abc
}

void func(std::string& abc)
{
  // method gets the original string object which can be modified without having to return it
}

void func(const std::string& abc)
{
  // method gets the original string object abc but is not able to modify it    
}

Разница в трех строках очень важна, потому что ваша программа может сэкономить много времени на создание копий входных параметров, которые вы обычно не хотели создавать.

например,

bool CmpString(std::string a, std::string b)
{
  return a.compare(b);
}

действительно дорого, потому что строки a и b всегда копируются. Вместо этого используйте

bool CmpString(const std::string& a, const std::string& b)

.

Это важно, потому что по умолчанию объекты с пересчетом ссылок не используются.

1
ответ дан 18 December 2019 в 05:15
поделиться

В C ++ любой объект, который вы объявляете в любой области, будет удален при выходе из области действия. В приведенном ниже примере конструктор по умолчанию вызывается при объявлении объекта, а деструктор вызывается при выходе, т.е. ~ MyClass.

void foo() {
  MyClass object;
  object.makeWonders();
}

Если вы объявляете указатель в функции, то сам указатель (4 байта для 32 bit systems) восстанавливается при выходе из области видимости, но память, которую вы могли выделить с помощью оператора new или malloc, будет задерживаться - это часто называется утечкой памяти.

void foo() {
  MyClass* object = new MyClass;
  object->makeWonders();
  // leaking sizeof(MyClass) bytes.
}

Если вам действительно необходимо выделить объект с помощью new, который необходимо удалить когда он выходит из области видимости, вы должны использовать boost :: scoped_ptr следующим образом:

void foo() {
  boost::scoped_ptr<MyClass> object(new MyClass);
  object->makeWonders();
  // memory allocated by new gets automatically deleted here.
}
0
ответ дан 18 December 2019 в 05:15
поделиться

В C ++ существует очень простое практическое правило:

Вся память автоматически освобождается, когда она выходит за пределы области видимости, если она не была выделена вручную.

Выделение вручную:

  • ] Любой объект, выделенный функцией new (), ДОЛЖЕН быть дераспределен соответствующей функцией delete ().
  • Любая память, выделенная функцией malloc (), ДОЛЖНА быть дераспределена соответствующей функцией free ().

Очень полезный шаблон проектирования в C ++ называется RAII ( Resource Acquisition Is Initialization ), который связывает динамические выделения с объектом с заданной областью, который освобождает выделение в его деструкторе.

В коде RAII вам больше не нужно беспокоиться о вызове delete () или free (), потому что они автоматически вызываются всякий раз, когда «объект привязки» выходит за пределы области видимости.

17
ответ дан 18 December 2019 в 05:15
поделиться

Здесь temp выделяется в стеке, и используемая им память автоматически освобождается при выходе из функции. Однако вы можете выделить ее в куче следующим образом:

int *temp = new int(2);

Чтобы освободить ее, вы должны сделать

delete temp;

Если вы размещаете свою переменную в стеке, обычно происходит следующее:

Когда вы вызываете свою функцию, он будет увеличивать эту вещь, называемую «указателем стека» - числом, указывающим, какие адреса в памяти должны быть «защищены» для использования ее локальными переменными. Когда функция вернется, он уменьшит указатель стека до исходного значения. Фактически ничего не делается с переменными, которые вы выделили в этой функции, за исключением того, что память, в которой они находятся, больше не «защищена» - все остальное может (и в конечном итоге будет) их перезаписать. Таким образом, вы не должны больше обращаться к ним.

Если вам нужно, чтобы выделенная память сохранялась после выхода из функции, используйте кучу.

11
ответ дан 18 December 2019 в 05:15
поделиться

Он не удаляется из памяти после выхода из функции.

Он остается в памяти, в кадре стека addTwo, до тех пор, пока какой-либо другой процесс (или тот же самый) повторно не использует эту часть памяти.

До этого момента временный доступ не определен.

6
ответ дан 18 December 2019 в 05:15
поделиться

temp выделен в стеке. Поэтому, когда функция возвращается, она исчезает.

Правила области видимости C ++ аналогичны C #.

4
ответ дан 18 December 2019 в 05:15
поделиться

Пожалуйста, посмотрите мой ответ на этот вопрос. Это может многое прояснить для oyu.

Как на самом деле работает автоматическое выделение памяти в C ++?

Я не просто публикую ссылку для хихиканья. Мой ответ - это подробный обзор (на очень вводном уровне) того, как работает управление памятью.

1
ответ дан 18 December 2019 в 05:15
поделиться

В этом случае и num, и temp являются локальными для этой функции. Когда функция вызывается, число, переданное в num, копируется из вызывающего объекта в переменную в стеке. Затем в стеке создается Temp. Когда вы возвращаете значение num, оно копируется обратно в вызывающую программу, а переменные temp и num, используемые в функции, удаляются.

0
ответ дан 18 December 2019 в 05:15
поделиться

Переменная temp выделена в стеке. Это означает, что он освобождается, когда функция возвращается.

См., Например:

0
ответ дан 18 December 2019 в 05:15
поделиться

В C, C ++ локальные переменные имеют класс автоматического хранения и хранятся в стеке .

Когда функция возвращает тогда стек разматывается, и локальные переменные становятся недоступными, но они все еще сохраняются в памяти, и поэтому, когда вы определяете переменную в функции, она может содержать значение мусора.

Это просто манипуляции с указателем стека в стеке и в памяти для локальных фактически удален.

0
ответ дан 18 December 2019 в 05:15
поделиться