Подтвердить что ты не робот

Сфера и возвращаемые значения в С++

Я начинаю снова с С++ и размышлял о сфере применения переменных. Если у меня есть переменная внутри функции, а затем я возвращаю эту переменную, переменная не будет "мертвой", когда она вернется, потому что область, в которой она была, закончилась?

Я пробовал это с функцией, возвращающей строку, и это действительно сработало. Может кто-нибудь объяснить это? Или, по крайней мере, указать мне на какое-то место, которое может объяснить это мне, пожалуйста.

Спасибо

4b9b3361

Ответ 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.
}

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