Возвращать интеллектуальные указатели по значению.
Как вы сказали, если вы вернете его по ссылке, вы не увеличите счетчик ссылок должным образом, что увеличивает риск удаления чего-либо в неподходящее время. Одного этого должно быть достаточно, чтобы не возвращаться по ссылке. Интерфейсы должны быть надежными.
Озабоченность стоимости в настоящее время спорные благодаря оптимизации возвращаемого значения (РВО), так что вы не будете нести приращение инкремента-декремент последовательности или что - то подобное , что в современных компиляторах. Итак, лучший способ вернуть a shared_ptr
- просто вернуться по значению:
shared_ptr<T> Foo()
{
return shared_ptr<T>(/* acquire something */);
};
Это совершенно очевидная возможность RVO для современных компиляторов C ++. Я точно знаю, что компиляторы Visual C ++ реализуют RVO, даже когда все оптимизации отключены. А с семантикой перемещения C ++ 11 эта проблема еще менее актуальна. (Но единственный способ быть уверенным - это профилировать и экспериментировать.)
Если вы все еще не уверены, у Дэйва Абрахамса есть статья, в которой приводятся аргументы в пользу возврата по значению. Я воспроизвожу здесь отрывок; Я настоятельно рекомендую вам прочитать всю статью:
Скажите честно: какие чувства вызывает у вас следующий код?
std::vector<std::string> get_names();
...
std::vector<std::string> const names = get_names();
Честно говоря, хотя мне следовало бы знать лучше, это меня заставляет нервничать. В принципе, при get_names()
возврате мы должны скопировать a vector
of string
s. Затем нам нужно скопировать его снова при инициализации
names
, и нам нужно уничтожить первую копию. Если string
в векторе есть N s, каждая копия может потребовать до N + 1 выделения памяти и целого ряда недружественных к кешу обращений к данным> по мере копирования содержимого строки.
Вместо того, чтобы противостоять этому виду беспокойства, я часто прибегал к передаче по ссылке, чтобы избежать ненужных копий:
get_names(std::vector<std::string>& out_param );
...
std::vector<std::string> names;
get_names( names );
К сожалению, этот подход далек от идеала.
- Код вырос на 150%
- Нам пришлось отбросить
const
-ness, потому что мы мутируем имена.
- Как любят напоминать функциональные программисты, мутации делают код более сложным для размышлений, подрывая ссылочную прозрачность и уравнительные рассуждения.
- У нас больше нет строгой семантики значений для имен.
Но действительно ли необходимо испортить наш код таким образом, чтобы повысить эффективность? К счастью, ответ оказывается отрицательным (особенно если вы используете C ++ 0x).