Единственной причиной, которую я использую awk
, является авторазделение:
awk '{print $3}' < file.in
Это печатает третье разграниченное пробелом поле в file.in
. Это немного легче, чем:
tr -s ' ' < file.in | cut -d' ' -f3
Локальная переменная 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
Термины «вытолкнуто» и «вытолкнуто» означают просто аналогию. Как видно из выходных данных сборки, компилятор резервирует всю память для локальных переменных и т.д. за один раз, вычитая подходящее значение из указателя стека.
Обычно управление памятью используется в контексте динамической памяти, которая создается
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)
.
Это важно, потому что по умолчанию объекты с пересчетом ссылок не используются.
В 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.
}
В C ++ существует очень простое практическое правило:
Вся память автоматически освобождается, когда она выходит за пределы области видимости, если она не была выделена вручную.
Выделение вручную:
Очень полезный шаблон проектирования в C ++ называется RAII ( Resource Acquisition Is Initialization ), который связывает динамические выделения с объектом с заданной областью, который освобождает выделение в его деструкторе.
В коде RAII вам больше не нужно беспокоиться о вызове delete () или free (), потому что они автоматически вызываются всякий раз, когда «объект привязки» выходит за пределы области видимости.
Здесь temp
выделяется в стеке, и используемая им память автоматически освобождается при выходе из функции. Однако вы можете выделить ее в куче следующим образом:
int *temp = new int(2);
Чтобы освободить ее, вы должны сделать
delete temp;
Если вы размещаете свою переменную в стеке, обычно происходит следующее:
Когда вы вызываете свою функцию, он будет увеличивать эту вещь, называемую «указателем стека» - числом, указывающим, какие адреса в памяти должны быть «защищены» для использования ее локальными переменными. Когда функция вернется, он уменьшит указатель стека до исходного значения. Фактически ничего не делается с переменными, которые вы выделили в этой функции, за исключением того, что память, в которой они находятся, больше не «защищена» - все остальное может (и в конечном итоге будет) их перезаписать. Таким образом, вы не должны больше обращаться к ним.
Если вам нужно, чтобы выделенная память сохранялась после выхода из функции, используйте кучу.
Он не удаляется из памяти после выхода из функции.
Он остается в памяти, в кадре стека addTwo, до тех пор, пока какой-либо другой процесс (или тот же самый) повторно не использует эту часть памяти.
До этого момента временный доступ не определен.
temp
выделен в стеке. Поэтому, когда функция возвращается, она исчезает.
Правила области видимости C ++ аналогичны C #.
Пожалуйста, посмотрите мой ответ на этот вопрос. Это может многое прояснить для oyu.
Как на самом деле работает автоматическое выделение памяти в C ++?
Я не просто публикую ссылку для хихиканья. Мой ответ - это подробный обзор (на очень вводном уровне) того, как работает управление памятью.
В этом случае и num, и temp являются локальными для этой функции. Когда функция вызывается, число, переданное в num, копируется из вызывающего объекта в переменную в стеке. Затем в стеке создается Temp. Когда вы возвращаете значение num, оно копируется обратно в вызывающую программу, а переменные temp и num, используемые в функции, удаляются.
Переменная temp выделена в стеке. Это означает, что он освобождается, когда функция возвращается.
См., Например:
В C, C ++ локальные переменные имеют класс автоматического хранения и хранятся в стеке .
Когда функция возвращает тогда стек разматывается, и локальные переменные становятся недоступными, но они все еще сохраняются в памяти, и поэтому, когда вы определяете переменную в функции, она может содержать значение мусора.
Это просто манипуляции с указателем стека в стеке и в памяти для локальных фактически удален.