Должны доступ к возвратам возврат или постоянные ссылки?
-
26-09-2019 - |
Вопрос
Предположим, у меня есть класс Foo
с А. std::string
член str
. Отказ Что должно get_str
вернуть?
std::string Foo::get_str() const
{
return str;
}
или
const std::string& Foo::get_str() const
{
return str;
}
Что более идиоматично в C ++?
Решение
Краткий ответ: это зависит :-)
С точки зрения производительности, возвращая ссылку (обычно) лучше: вы сохраняете создание нового std::string
объект. (В этом случае создание достаточно дорого, а размер объекта достаточно высокий, чтобы оправдывать Сделайте этот выбор, по крайней мере, стоит рассмотреть - но это не всегда так. С меньшим или встроенным типом разница производительности может быть незначительной, или возвращение по значению может даже быть дешевле).
С точки зрения безопасности, возвращая копию исходного значения может быть лучше, так как постоянная связь может быть выброшена вредоносными клиентами. Это особенно необходимо учитывать, если метод является частью общедоступного API, т.е. вы (R Team) не имеют полного контроля над тем, как используется возвращенное значение (MIS).
Другие советы
Одной из целей наличия метода аксессуаров является попытка, по крайней мере, в некоторой степени, чтобы аннотация ваша реализация класса из его интерфейса.
Возвращение по значению лучше, потому что нет проблем с жизни с ссылочным объектом. Если вы решите не иметь std::string
член, но, скажем, std::stringstream
или создать std::string
На лету вам не нужно менять интерфейс.
Возвращаясь const
Ссылка не является противоположностью принимать параметр Const Refect, принимая значение по const
Ссылка не привязывает ваше внутреннее представление данных на внешний интерфейс.
В целом (если нет доказанной проблемы производительности) Я бы вернул по стоимости.
Прежде всего, есть семантическое различие, если ваша собственность меняется, вы хотите, чтобы ваши клиенты были обновлены из изменения или получить значение в момент вызова функции?
Существует очевидная проблема правильности, если вы вернетесь по ссылке, сущность, вызывающая функцию, может удерживать ссылку, и может использовать ее после того, как ваш объект был разрушен (что не так хорошо).
Другая проблема с несколькими резьбой кода, если один поток читается из ссылки Const, пока вы обновляете вариабельную информацию для многих неприятностей.
В любом случае, я думаю, наиболее распространенным применением является когда вызывающий абонент функции хранит значение в переменной.
string val = obj->get_str();
// use val now
Если это правда (в отличие от cout << obj->get_str()
где нет переменной), вы всегда должны построить новую строку для val
Даже если вы вернетесь по ссылке, и поскольку компиляторы могут выполнять RVO Версия по значению не будет под управлением варианта By-Const-Ref.
В заключение: Если вы знаете, это проблема производительности а также Вы Конечно что возвращаемое значение не будет храниться дольше, чем ваш объект будет существовать а также Вы не ожидаете использовать из разных потоков, то это нормально, чтобы вернуться на ссылку Const.
Возвращая по значению означает, что вам не нужно иметь внутреннюю std :: string, хранящуюся где-то в классе, для которого вы возвращаетесь.
В чистом виде виртуального метода предпочтительно не предполагать, что std :: string будет там и, следовательно, чтобы вернуть std :: string по значению.
В конкретном классе, где ясно, что элемент STD :: string, и вы просто собираетесь вернуть ссылку на него, вы можете, для эффективности, вернуть ее на Const Reference. Даже если вы должны изменить его позже, вам не нужно менять функциональность, которые используют класс.
В многопоточной модели, в которой внутренняя строка может измениться между вызовами, конечно, вам, вероятно, нужно для возврата по значению (предполагая, что пользователи класса получат «моментальный» представление строкового значения во время завершения звонок).
Возвращение посредством ссылки, как правило, более эффективно. У меня, однако, у меня есть нерешимый класс String Class, который вы можете эффективно возвращаться по значению, и я использовал для того, чтобы использовать это довольно часто.
Кстати, некоторые рекомендуют вернуть std :: string by const Right. Я не думаю, что это лучший способ сделать это, так как предотвращает разрешение пользователя «поменять» в локальную переменную.
AFAIK, правило такое же, как тот, который используется при принятии решения о том, следует ли принимать функциональный параметр по значению или ссылке Const. Если то sizeof
Возвращенная стоимость достаточно мала достаточно мала, я склоннусь использовать возвращение копии еще вернуть ссылку Const.
Я считаю, что второе внедрение (Const Reference) правильно, как:
- Возвращенный объект неизменен и поэтому поддерживает правила инкапсуляции.
- Это немного более эффективно, так как нет копирования
str
.
Однако первый подход будет работать почти хорошо.
Как правило, вы должны вернуть стручки по значению (например, INT, CORM, CHAR, LONG ETC,) и CONT RESSERT для более сложных типов:
int getData() const;
short getMoreData() const;
const std::string& getName() const;
const ComplexObject& getComplexData() const;
Это зависит от того, что вы хотите сделать с возвращаемой стоимостью.
Это лучше, если вы просто хотите сделать запрос и не модифицировать str
.
const std::string& Foo::get_str() const
{
return str;
}
В противном случае иди на это:
std::string& Foo::get_str()
{
return str;
}
И если вы хотите Копировать / клон из str
, Затем используйте это:
std::string Foo::get_str() const
{
return str;
}