Какая польза от передачи константных ссылок на примитивные типы? - PullRequest
15 голосов
/ 23 марта 2009

В проекте, который я поддерживаю, я вижу много такого кода для простых get / set методов

const int & MyClass::getFoo() { return m_foo; }

void MyClass::setFoo(const int & foo) { m_foo = foo; }

Какой смысл делать это вместо следующего?

int MyClass::getFoo() { return m_foo; }  // Removed 'const' and '&' 

void MyClass::setFoo(const int foo) { m_foo = foo; }  // Removed '&'

Передача ссылки на примитивный тип требует таких же (или более) усилий, как и передача самого значения типа, верно?
В конце концов, это просто число ...
Это просто попытка микрооптимизации или есть реальная выгода?

Ответы [ 6 ]

20 голосов
/ 23 марта 2009

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

const &int x = myObject.getFoo();
cout<<x<<endl;
//...
cout<<x<<endl;//x might have changed

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

Существует небольшая разница и для модификатора, но, опять же, вероятно, это не то, что стоит делать или было задумано.

void test1(int x)
{
  cout<<x<<endl;//prints 1
}

void test2(const int &x)
{
  cout<<x<<endl;//prints 1 or something else possibly, another thread could have changed x
}

int main(int argc, char**argv)
{
  int x = 1;
  test1(x);
  //...
  test2(x);
  return 0;
}

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

7 голосов
/ 23 марта 2009

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

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

Как правило, ints и адреса имеют одинаковую длину байта в низкоуровневых реализациях. Таким образом, время копирования int в качестве возвращаемого значения для функции эквивалентно времени копирования адреса . Но в случае, если возвращается int , поиск не выполняется, поэтому производительность увеличивается.

5 голосов
/ 23 марта 2009

Основное различие между возвратом значения и возвратом константной ссылки заключается в том, что вы можете затем const_cast эту ссылку и изменить значение.

Это пример плохого дизайна и попытки создать умный дизайн, где простого и лаконичного дизайна было бы более чем достаточно. Вместо того, чтобы просто возвращать значение, автор заставляет читателей кода задуматься о том, какое намерение он имел.

4 голосов
/ 23 марта 2009

Там не так много пользы. Я видел это в каркасе или сгенерированных макросами геттеров и сеттеров раньше. Макрокод не различал примитивные и не POD-типы и просто использовал const type& по всем направлениям для сеттеров. Я сомневаюсь, что это проблема эффективности или подлинного недоразумения; скорее всего, это проблема согласованности.

2 голосов
/ 23 марта 2009

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

0 голосов
/ 23 марта 2009

Нет смысла и пользы, кроме

void MyClass::setFoo(const int foo)
void MyClass::setFoo(const int& foo)

так как тогда вы не сможете повторно использовать переменную 'foo' внутри реализации 'setFoo'. И я верю, что int & просто потому, что Гай просто привык передавать все по константной ссылке, и в этом нет ничего плохого.

...