Ссылка оператора на возвращаемое значение? - PullRequest
1 голос
/ 19 ноября 2011

Я изучаю объектно-ориентированное программирование на C ++. У меня есть некоторые сомнения по поводу следующего кода:

class Vehicle 
{ 
  protected: 
    string license ; int year ;
  public:
    Vehicle(const string &myLicense, const int myYear) : license(myLicense), year(myYear){}

    const string getDesc() const 
    {
      return license + " from " + stringify(year);
    } 
    const string &getLicense() const {return license;} 
    const int getYear() const {return year;} 
};
  • что означает использование оператора ссылки (&) для возвращаемого значения функции. Почему это удобно использовать? Я думаю, что результат точно такой же, и вы используете одинаковое количество памяти независимо от того, используете ли вы (&) в функции getlicense.

  • почему этот код использует зарезервированное слово const? Я вижу, что это может работать с использованием его. Есть ли преимущество использования const в коде?

Заранее спасибо за помощь, ребята.

Ответы [ 5 ]

2 голосов
/ 19 ноября 2011

Используется, чтобы избежать ненужного копирования при возврате объекта, хотя это также зависит от сайта вызова, так как на сайте вызова можно сделать копию, а копию не сделать:

std::string copy = veh.getLicence(); //makes a copy
const std::string & notAcopy = veh.getLicence(); //does not make a copy

//and most importantly here
size_t size = veh.getLicense().size(); //doesn't make a copy!

Возвращение ссылки особенно помогает в цепочечных вызовах функций.Если вы не хотите вызывать функцию для копии в вызовах функций, связанных с цепочкой, то вам нужно вернуться по ссылке, чтобы убедиться, что вызов функции из цепочки выполнен для оригинала. объект, как в третьем примере выше.

Есть некоторые классы, тип возвращаемого значения которых должен быть ссылочный тип (или указатель тип), в противном случаеэто не будет работать, потому что их конструкторы копирования были отключены, объявив их private.Наиболее часто используемые такие классы - это классы IOStream, например std::istream, std::ostream и все классы, производные от них.В таких случаях вы должны использовать std::ostream& в качестве возвращаемого типа функции (обычно эти функции operator<< перегружены).

2 голосов
/ 19 ноября 2011

Возвращая ссылку на лицензию, вы сохраняете операцию копирования, которая потребует выделения памяти. Делая это константной ссылкой, он не позволяет вызывающим абонентам изменять внутреннее состояние.

1 голос
/ 19 ноября 2011

Если у вас есть const string &getLicense() const {return license;}, это означает, что вы возвращаете значение лицензии по ссылке . Без & вы вернетесь по значению. Цитирование

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

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

Итак, подведем итог, & используется для возврата по ссылке, что быстрее, чем возврат по значению (потому что вы просто возвращаете ссылку и не копируете объект), и используется const чтобы запретить модификацию.


Подробнее о возврате по ссылке можно прочитать здесь, на C ++ - FAQ-lite .

0 голосов
/ 19 ноября 2011

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

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

  1. Вы возвращаете ссылку на некоторый ранее существующий объект (например, многие операторы iostreams передают ссылку на iostream и возвращают ссылку на тот же iostream; аналогично, оператор присваивания обычно return *this; ).
  2. Функция динамически распределяет объект, который она возвращает. В этом случае, однако, гораздо чаще возвращать указатель, чем ссылку.

Я бы даже сказал, что в большинстве случаев недостаток копирования (или, по крайней мере, эффективность, полученная благодаря отсутствию копирования) является более или менее важной причиной, чем основная причина. Вы возвращаете ссылку. В случае iostream вы возвращаете ссылку в первую очередь потому, что iostream - это в основном объект типа «идентичность» - то есть вы не можете скопировать или назначить его. Вы создаете один, используете ссылки на этот единственный объект, и когда вы закончите, вы уничтожаете его.

Когда вы передаете ссылку на объект, основной целью часто является удаление копии. Однако, когда вы возвращаете ссылку, это происходит гораздо реже.

Я бы также отметил, что в течение некоторого времени в большинстве компиляторов реализована оптимизация возвращаемых значений и оптимизация именованных возвращаемых значений (RVO / NRVO). Это означает, что возврат значения часто не теряет никакой эффективности по сравнению с возвратом ссылки в любом случае (на самом деле, произойдет, если компилятор внутренне превратит ваш код, который возвращает значение, в код, который получает ссылка и записывает непосредственно в значение родителя).

Итог: возвращение ссылки не так просто и очевидно, как может показаться на первый взгляд. За исключением нескольких ситуаций, в которых рутина (операторы вставки, извлечения и присваивания являются наиболее очевидными) вам, вероятно, действительно нужно подумать и понять, что вы делаете, а не просто очевидной оптимизации.

0 голосов
/ 19 ноября 2011

Пожалуйста, лучше отформатируйте свой код!Это излишне сложно проанализировать:

class Vehicle 
{ 
public:
  Vehicle(const string & myLicense, const int myYear)
    : license(myLicense)
    , year(myYear) 
  {}

  const string getDesc() const 
  {
    return license + " from " + stringify(year);
  } 
  const string & getLicense() const {return license;} 
  const int getYear() const {return year;} 
protected:
  // good convention: put details that users shouldn't be paying attention to 
  // below the public parts that they *should* be paying attention to
  string license;
  int year;
};

Возвращение const string & означает, что вы предоставляете доступ только для чтения (const) к внешнему миру, чтобы напрямую взаимодействовать (посредством ссылки) с лицензией этого объекта (потому чтоэто то, что делает getLicense ().

Обычно это вариант эффективности.то есть вы можете вернуть лицензию по значению (копировать), но затем вы копируете содержимое лицензии.Таким образом, вы просто предоставляете прямой доступ, но при условии, что он доступен только для чтения.

const в возврате означает, что он доступен только для чтения.const в конце объявления метода означает, что вы заявляете, что этот метод не изменит значения этого объекта.

Последнее особенно важно, если у вызывающей стороны есть экземпляр const объекта Vehicle.Вызывающей стороне не будет разрешено вызывать неконстантные методы, потому что они имеют доступ только для чтения к своему экземпляру Vehicle.

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