С++ возвращает локальный объект

Несколько сотрудников и я обсуждаем, что происходит, когда локальная переменная (выделенная в стеке) возвращается из метода С++.

Следующий код работает в unit test, но я считаю, что это только потому, что unit test повезло и не пытается повторно использовать память в стеке, используемом obj.

Работает ли это?

static MyObject createMyObject() {
    MyObject obj;
    return obj;
}

Ответы

Ответ 1

Что происходит, так это то, что конструктор копирования вызывается для создания копии локального объекта, и это то, что получает вызывающий.

Компилятор может исключить копию в процессе, называемом copy elision, но это по усмотрению компилятора - у вас мало контролировать его.

Этот шаблон способен создавать проблемы, о которых вы боитесь, но только если вы возвращаете указатель или ссылку на локальный объект.

Ответ 2

obj, а затем он копируется из метода/функции с помощью конструктора копирования объекта.

Вы можете сделать это obj не для того, чтобы быть в стеке, объявив его static тоже. Возврат объекта также возвращает копию, но объект не создается при каждом вызове функции. Затем вы можете вернуть объект в качестве ссылки:

static MyObject & createMyObject() {
    static MyObject obj;
    return obj;
}

(здесь нет копии, а также obj создается только один раз, и его адрес остается постоянным во время выполнения).

Ответ 3

Вы возвращаете объект по значению, поэтому он вызывается конструктором копирования, и КОПИЯ исходного объекта будет возвращена и сохранена в стеке вызывающего абонента. Если этот метод возвращает указатель (или ссылку) локальной переменной, он не работает.

Ответ 4

Возвращается A копия MyObject. Что должно быть хорошо, если MyObject имеет конструктор копирования, который копирует все правильно. Обратите внимание, что у него может быть конструктор копирования даже без явного перечисления одного. Определенный компилятором конструктор копии по умолчанию (который присваивает все по порядку) может отлично работать для ваших целей.

Ответ 5

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

Ответ 6

Предполагая, что все остальные просто пропустили очевидный источник путаницы в этом вопросе - static:

Вы не объявляете экземпляр MyObject, созданный в и возвращаемый из createMyObject, как имеющий статическую продолжительность хранения; скорее, вы объявляете функцию createMyObject как имеющую внутреннюю привязку.