Это хорошая идея, чтобы всегда вернуть ссылки на переменные членов Getter?
-
04-10-2019 - |
Вопрос
Если у меня есть класс, который имеет много int
, float
, а также enum
Переменные-члены, считается, что это считается эффективной и / или хорошей практикой, чтобы вернуть их в качестве ссылок, а не копии, и вернуть постоянные ссылки, где никакие изменения не должны быть сделаны? Или есть причина, по которой я должен вернуть их как копии?
Решение
Нет причин возвращать примитивные типы, такие как int
а также float
по ссылке, если вы не хотите, чтобы они были изменены. Возвращая их посредством ссылки на самом деле менее эффективна, потому что она ничего не спасает (int
S и указатели, как правило, такие же размер), в то время как разрабатывание на самом деле добавляет накладные расходы.
Другие советы
Если они постоянные ссылки, возможно, это нормально. Если они не постоянные ссылки, вероятно, нет.
Что касается эффективности - на 64-битной машине, ссылки будут 64-битные количества (указатели в маскировке); int
а также float
а также enum
будет меньше. Если вы вернете ссылку, вы заставляете уровень косвествия; Это менее эффективно.
Таким образом, особенно для встроенных типов в качестве возвращаемых значений, обычно лучше вернуть значение, а не ссылку.
Некоторые случаи необходимо:
Посмотрите на перегруженное operator[]
для любого класса. У него обычно есть две версии. Мутирующая версия должна вернуть ссылку.
int &operator[](int index); // by reference
int operator[](int index) const; // by value
В общем, все в порядке, чтобы разрешить доступ к членам классов доверенным лицам классом, например, друзьями. В случае, если эти доверенные лица также должны изменять государство, ссылки или указатели на членов класса, являются единственными вариантами.
Во многих случаях ссылки обычно упрощают синтаксис, например, где «V» - вектор STL.
v.at(1) = 2 vs *(v.at(1)) = 2;
Это, вероятно, в основном вопрос стиля или предпочтения. Одна из причин для не возвратных ссылок заключается в том, что вы используете GetTers и Setters, чтобы позволить вам изменить реализацию этих членов, если вы изменили частный член другому типу или полностью удалили его, потому что он может быть вычислен, то у вас больше нет Возможность возвращать ссылку, поскольку нечего ссылаться.
С другой стороны, возвращающиеся ссылки на нетривиальные типы (составные классы) могут немного ускорить свой код, создавая копию, и вы можете позволить тем членам назначаться через возвращенную ссылку (при желании).
Почти почти, Const ссылки лучше. Для INTS и таких Theres нет смысла, потому что вы хотели бы, чтобы они были изменены или потому, что они одинаковы (или почти) в качестве ссылки.
Так что да, это хорошая идея. Я предпочитаю другой язык или взломать на мои собственные вещи C ++ и просто позвольте VAR быть публичным (еще раз просто мои собственные вещи)
Это вопрос производительности в основном, но с точки зрения надежности, я бы сказал, что предпочтительно возвращать значения вместо Const ссылок. Причина, находящаяся в том, что даже Const ссылки ослабляют инкапсуляцию. Учти это:
struct SomeClass
{
std::vector<int> const & SomeInts () const;
void AddAnInt (int i); // Adds an integer to the vector of ints.
private:
std::vector<int> m_someInts;
};
bool ShouldIAddThisInt(int i);
void F (SomeClass & sc)
{
auto someInts = sc.SomeInts ();
auto end = someInts.end ();
for (auto iter = someInts.begin (); iter != end; ++iter)
{
if (ShouldIAddThisInt(*iter))
{
// oops invalidates the iterators
sc.AddAnInt (*iter);
}
}
}
Таким образом, если это делает семантически смысл, и мы можем избежать чрезмерных динамических распределений, я предпочитаю возврат по значению.
Геттерс для выбросов класса говорят Exhaust Car.emit()
, где машина только что создала Exhaust
.
Если вы обязаны написать const Seat& Car.get_front_seat()
позже сидеть в Driver
, вы можете сразу заметить, что что-то не так.
Коррекольно, вы бы предпочли писать Car.get_in_driver(Driver)
который затем звонит напрямую seat.sit_into(Driver)
.
Этот второй метод легко избегает этих неловких ситуаций, когда вы get_front_seat
Но дверь закрыта, и вы практически вытесните водителя через закрытую дверь. Помните, вы просили только сиденье! :)
В общем: Всегда возвращайте по значению (и полагаться на оптимизацию возврата Value), или осознайте время изменения вашего дизайна.
Фон: классы были созданы, так что данные могут быть соединены вместе со своими функциональными возможностями доступа, локализация ошибок и т. Д. Таким образом, классы никогда не являются активностью, но ориентированы на данные.
Дальнейшие подводные камни: В C ++, если вы вернетесь к Const Ref, то вы можете легко забыть, что это только Ref, и как только ваш объект разрушится, вы можете оставить недействительным Ref. В противном случае этот объект будет скопирован Как только это покидает добыча в любом случае. Но ненужденные копии избегают компилятора, см. Оптимизация возврата стоимости.