Сфера и возвращаемые значения в С++
Я начинаю снова с С++ и размышлял о сфере применения переменных.
Если у меня есть переменная внутри функции, а затем я возвращаю эту переменную, переменная не будет "мертвой", когда она вернется, потому что область, в которой она была, закончилась?
Я пробовал это с функцией, возвращающей строку, и это действительно сработало.
Может кто-нибудь объяснить это? Или, по крайней мере, указать мне на какое-то место, которое может объяснить это мне, пожалуйста.
Спасибо
Ответы
Ответ 1
Когда функция завершается, следующие шаги:
-
Возвращаемое значение функции скопирован в местозаполнитель, который был поставьте на стек для этой цели.
-
Все после кадра стека указатель выскользнул. Это разрушает все локальные переменные и аргументы.
-
Возвращаемое значение сбрасывается с стек и назначается как значение функции. Если значение функция не привязана ни к чему, не выполняется присвоение, а значение теряется.
-
Адрес следующей инструкции для выполнения вылетает из стека, и процессор возобновляет выполнение в эта инструкция.
Стек и куча
Ответ 2
Когда вы возвращаете значение, делается копия. Объем локальной переменной заканчивается, но выполняется копия и возвращается вызывающей функции. Пример:
int funcB() {
int j = 12;
return j;
}
void A() {
int i;
i = funcB();
}
Значение j (12) копируется и возвращается в i, так что я получаю значение 12.
Ответ 3
Это зависит от того, какую переменную вы возвращаете. Если вы возвращаете примитив, то он возвращается копией, а не ссылкой, поэтому значение копируется в начало стека (или, чаще всего, помещается в регистр), где вызывающая функция может его получить. Если вы выделяете объект или память в кучу и возвращаете указатель, тогда он не умирает, потому что он находится в куче, а не в стеке. Однако, если вы выделите что-то в стеке и вернете его, это будет плохо. Например, любой из них будет очень плохим:
int *myBadAddingFunction(int a, int b)
{
int result;
result = a + b;
return &result; // this is very bad and the result is undefined
}
char *myOtherBadFunction()
{
char myString[256];
strcpy(myString, "This is my string!");
return myString; // also allocated on the stack, also bad
}
Ответ 4
Просто для немного большего количества ориентированного на модель памяти объяснения: когда вызывается функция, создается временное пространство для того, чтобы функция помещала свои локальные переменные, называемые кадром. Когда функция (callee) возвращает свое значение, она помещает возвращаемое значение в кадр вызываемой функции (вызывающей стороны), а затем кадр вызываемого абонента уничтожается.
Часть "frame is destroy" - это то, почему вы не можете возвращать указатели или ссылки на локальные переменные из функций. Указатель фактически является местом памяти, поэтому возвращение ячейки памяти локальной переменной (по определению: переменная внутри кадра) становится некорректным после уничтожения кадра. Поскольку кадр звонка разрушается, как только он возвращает свое значение, любой указатель или ссылка на локальную переменную сразу же неверны.
Ответ 5
Локальная переменная копируется в возвращаемое значение. Конструкторы копирования вызываются для нетривиальных классов.
Если вы вернете указатель или ссылку на локальную переменную, у вас возникнут проблемы - так же, как предложила ваша интуиция.
Ответ 6
Это зависит от типа возвращаемого элемента. Если вы возвращаетесь по значению, для возврата к вызывающей стороне создается новая копия переменной. Я делаю так, что вам не нужно беспокоиться о жизни объекта, но вам может потребоваться беспокоиться о расходах на копирование объектов (но, пожалуйста, не преждевременно оптимизируйте - правильность гораздо важнее):
std::string someFunc( std::string& const s)
{
return s + "copy";
}
Если функция возвращает ссылку, то вам нужно быть осторожным с тем, что вы возвращаете, потому что ее жизненное время должно выходить за пределы срока службы функции, и вызывающий абонент не обязательно сможет delete
его, если вы используя new
для создания объекта:
std::string& someFunc2( std::string const& s)
{
return s + "reference to a copy"; // this is bad - the temp object created will
// be destroyed after the expression the
// function call is in finishes.
// Some, but not all, compilers will warn
// about this.
}
Конечно, возвращающие указатели будут иметь схожие соображения по времени.