С++ возвращает локальный объект
Несколько сотрудников и я обсуждаем, что происходит, когда локальная переменная (выделенная в стеке) возвращается из метода С++.
Следующий код работает в 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
как имеющую внутреннюю привязку.
Ответ 7
Это работает отлично. Он создаст временную анонимную переменную, которая возвращает MyObject:
Анонимные переменные и объекты
привязка временного объекта к ссылке на const