Объем и возвращаемые значения в C++

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

Чтобы заставить это работать, вы можете попробовать:

useEffect(() => {
    firebase.getBooks().then(books => setBooks(books))
  }, []);
25
задан dmckee 8 November 2008 в 21:22
поделиться

6 ответов

Когда функция завершается, выполняются следующие шаги:

  • Возвращаемое значение функции копируется в заполнитель, который был помещен в стек для этой цели.

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

  • Возвращаемое значение выталкивается из стека и присваивается в качестве значения функции. Если значение функции никому не назначено, присвоение не происходит, и значение теряется.

  • Адрес следующей команды для выполнения извлекается из стека, и ЦПУ возобновляет выполнение с этой командой.

Стек и куча

44
ответ дан 28 November 2019 в 18:32
поделиться

Когда вы возвращаете значение, создается копия. Область действия локальной переменной заканчивается, но копия создается и возвращается вызывающей функции. Пример:

int funcB() {
  int j = 12;
  return j;
}

void A() {
  int i;
  i = funcB();
}

Значение j (12) копируется и возвращается в i, так что я получу значение 12.

3
ответ дан 28 November 2019 в 18:32
поделиться

Это действительно зависит от того, какую переменную вы возвращаете. Если вы возвращаете примитив, то он возвращается копией, а не ссылкой, поэтому значение копируется в верхнюю часть стека (или, чаще всего, помещается в регистр), где вызывающая функция может его получить. Если вы выделяете объект или память в куче и возвращаете указатель, он не умирает, потому что он находится в куче, а не в стеке. Однако если вы разместите что-то в стеке и вернете это, это будет плохо. Например, любой из них будет очень плохим:

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
ответ дан 28 November 2019 в 18:32
поделиться

Просто для более подробного объяснения, ориентированного на модель памяти: когда вызывается функция, создается временное пространство для функции, в которую помещаются ее локальные переменные, называемые кадром . Когда функция (callee) возвращает свое значение, она помещает возвращаемое значение в фрейм функции, вызвавшей ее (callere), и затем фрейм callee уничтожается.

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

3
ответ дан 28 November 2019 в 18:32
поделиться

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

Если вы вернете указатель или ссылку на локальную переменную, у вас будут проблемы - как и подсказывает ваша интуиция.

2
ответ дан 28 November 2019 в 18:32
поделиться

Это зависит от типа возвращаемого товара. Если вы возвращаете по значению, создается новая копия переменной для возврата вызывающей стороне. В этом случае вам не нужно беспокоиться о времени жизни объекта, но вам, возможно, придется беспокоиться о стоимости копирования объектов (но, пожалуйста, не оптимизируйте преждевременно - правильность гораздо важнее):

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.
}

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

2
ответ дан 28 November 2019 в 18:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: