Возвращать интеллектуальные указатели по значению.
Как вы сказали, если вы вернете его по ссылке, вы не увеличите счетчик ссылок должным образом, что создает риск удаления чего-либо в неподходящее время. Одного этого должно быть достаточно, чтобы не возвращаться по ссылке. Интерфейсы должны быть надежными.
Вопрос о стоимости в настоящее время остается спорным благодаря оптимизации возвращаемого значения (RVO), поэтому вы не будете последовательность инкремент-инкремент-декремент или что-то подобное в современных компиляторах. Итак, лучший способ вернуть 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()
возвращается, мы должны скопировать vector
из string
s. Затем нам нужно скопировать его снова, когда мы инициализируем names
, и нам нужно уничтожить первую копию. Если в векторе имеется N string
, каждая копия может потребовать до N + 1 выделения памяти и целого ряда недружественных к кешу обращений к данным> по мере копирования содержимого строки.
Вместо того, чтобы противостоять подобному беспокойству, я часто прибегал к передаче по ссылке, чтобы избежать ненужных копий:
get_names(std::vector<std::string>& out_param );
...
std::vector<std::string> names;
get_names( names );
К сожалению, этот подход далек от идеала.
- Код вырос на 150%
- Нам пришлось отказаться от
const
-ness, потому что мы меняем имена.
- Как любят напоминать функциональные программисты, мутации делают код более сложным для размышлений, подрывая ссылочную прозрачность и эквациональные рассуждения.
- У нас больше нет строгой семантики значений для имен.
Но действительно ли необходимо испортить наш код таким образом, чтобы повысить эффективность? К счастью, ответ оказывается отрицательным (особенно если вы используете C ++ 0x).
person
In silico
schedule
17.05.2012