C ++ метод get - возврат по значению или по ссылке - PullRequest
6 голосов
/ 30 мая 2010

У меня очень простой вопрос, но, к сожалению, я не могу сам найти ответ.

Предположим, у меня есть некоторая структура данных, которая содержит настройки и действует как карта настроек. У меня есть метод GetValue(const std::string& name), который возвращает соответствующее значение.

Теперь я пытаюсь выяснить - какой подход с возвратом стоимости был бы лучше. Очевидное означает, что мой метод действует как

std::string GetValue(const std::string& name) const

и вернуть копию объекта и положиться на RVO в значениях производительности.

Другой будет означать создание двух методов

std::string& GetValue(...)
const std::string& GetValue(...) const

, что обычно означает дублирование кода или использование некоторых злых констант, дважды использующих одну из этих подпрограмм.

# Q

Что бы вы выбрали в такой ситуации и почему?

Ответы [ 4 ]

6 голосов
/ 30 мая 2010

На самом деле я бы, вероятно, использовал:

std::string GetValue(const std::string& name) const;
// or
const std::string* GetValue(const std::string& name) const;

void SetValue(std::string name, std::string value);

Первый сеттер:

  • Передача по значению в SetValue позволяет компилятору несколько оптимизаций, которые нельзя выполнить с помощью передачи по const-ссылке, это было объяснено в статье Дейва Абрахамса, «Хотите скорость? Передайте по значению».
  • Использование Setter обычно лучше, потому что вы можете проверить установленное значение, тогда как с простой ссылкой у вас нет гарантии, что вызывающая сторона не сделает глупостей с данными.

Для получателя:

  • Возвращение копией кажется пустой тратой, так как в большинстве случаев вы не будете изменять возвращаемый объект (для карты настроек), однако указатель или ссылка означают, что объект с псевдонимом будет жить достаточно долго, если вы не можете гарантировать это тогда точка спорна: возврат по значению. Также копирование позволяет избежать раскрытия внутренних деталей, например, если вы внезапно переключились на std::wstring, потому что вам нужны некоторые настройки в UTF-8 ...
  • Если вам нужна производительность, тогда вы готовы пойти на некоторые уступки в этом отделе. Однако ссылка не позволяет вам сигнализировать об отсутствии свойства (если у вас нет магического значения), в то время как указатель облегчает его (NULL уже вырезан для вас).
6 голосов
/ 30 мая 2010

Это зависит от использования. Должен ли GetValue("foo") = "bar" иметь смысл? В этом случае возврат по значению не делает то, что вы хотите.

2 голосов
/ 30 мая 2010

Если вы можете вернуться по постоянной ссылке, сделайте. Единственная причина вернуть класс управления памятью, такой как std :: string, по значению, потому что это временная строка.

1 голос
/ 30 мая 2010

Это очень «чувствительная» точка C ++. ИМХО, это одно из самых слабых мест в дизайне C ++. AFAIK нет действительно хорошего выбора, который будет и выглядеть и работать хорошо.

Стоит отметить, что оптимизация RVO обычно выполняет только часть работы. Без этого типичное выражение, подобное этому:

std::string txt = GetValue("...");

фактически произведет 2 копии! Зависит от компилятора, но обычно оптимизация RVO исключает только одну копию, а другая все еще там.

...