Должны доступ к возвратам возврат или постоянные ссылки?

StackOverflow https://stackoverflow.com/questions/4613823

Вопрос

Предположим, у меня есть класс 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) правильно, как:

  1. Возвращенный объект неизменен и поэтому поддерживает правила инкапсуляции.
  2. Это немного более эффективно, так как нет копирования 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;
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top