Возможный дубликат:
как «вернуть объект» в C ++
Привет ребята!
Если мне нужно вернуть объект из функции (и он не является геттером, а также эта функция по какой-то причине не может быть реализована как конструктор, например, существует конструктор с такой же сигнатурой и различной семантикой), как лучше реализовать этот?
Например, можно предложить следующие варианты:
1) Вернуть сам объект:
MyClass GetMyClass() {
MyClass a;
...
return a;
}
В большинстве случаев RVO, http://en.wikipedia.org/wiki/Return_value_optimization выполняется, конструкторы копирования не вызываются и нет служебных данных.
Недостаток этого подхода заключается в том, что, несмотря на RVO, вы должны указать автора копирования MyClass, но, как указано в Руководстве по стилю Google C ++ …
Неявное копирование объектов в C ++ является богатым источником ошибок и проблем с производительностью.
2) Вернуть указатель на объект:
MyClass* GetMyClass() {
MyClass* a= new MyClass();
...
return a;
}
В этом случае возникают накладные расходы из-за выделения памяти в куче. Это как-то тормозит программу из-за системного вызова malloc.
Кроме того, вы должны освободить память вне этой функции, что означает, что выделение и освобождение выполняются в разных логических единицах. Как уже упоминалось здесь, Почему плохая память в функции и ее освобождение снаружи — плохая идея? это чаще всего плохая идея.
3) Передать значение по ссылке или по указателю:
void GetMyClass(MyClass& a) {
...
}
В этом случае код становится уродливым и плохо читаемым
Какова лучшая практика?
Какой из них вы используете в своих проектах и какие критерии являются наиболее важными, когда вы работаете над большим проектом?
Два довольно просто. Да, malloc может быть медленным, но имеет ли это значение в вашем случае? Вам нужно место для этого объекта откуда-то. Также обратите внимание на ответы на вопрос, на который вы указываете, проблема существует только в логических единицах. Посмотрите, есть ли у вас проблема, а затем попытайтесь ее исправить, а не предварительно оптимизируйте.
Вы могли бы потенциально сделать свою собственную версию новой, которая использует бесплатный магазин и ресурсы менеджеров самостоятельно. Однако, если вы не измерили и не обнаружили, что новое является проблемой, это может привести к ошибкам.
Один из способов помочь решить проблемы со свободными указателями — использовать станд :: shared_ptr. Таким образом, вам не нужно беспокоиться об освобождении объекта, если вы всегда используете его с помощью умного указателя.
Вы упустили очевидную возможность возврата конструируемого объекта перемещения: возвращаемое значение может по-прежнему сокращать накладные расходы, но вы не рискуете получить случайные копии. Там, где C ++ 2011 недоступен, я бы сделал тип копируемым и возвращал бы по значению.
Там, где нет ни перемещения, ни копирования, я бы вернул указатель. Конечно, я не вернул бы голый указатель, но std::unique_ptr<T>
(или же std::auto_ptr<T>
(где недоступно): использование интеллектуального указателя позволяет избежать риска утечки памяти, но выбор более легкого указателя, а не, например, std::shared_ptr<T>
, не принимает окончательное политическое решение о том, как объект поддерживается. В тех случаях, когда объект должен быть освобожден каким-то забавным способом, он может иметь функцию удаления.