2015-05-31 3 views
1

Я смотрел видео и увидел этот код:Переходя константные ссылки на функцию

class Dog { 
    public: 
     Dog() : age(3), name("dummy") {} 
     void setAge(const int &a) { age = a; } 
    private: 
     int age; 
     std::string name; 
}; 

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

В таком элементарном примере трудно увидеть преимущество передачи const ссылки на функцию.

Есть ли причина, почему вы хотите сделать ссылкой a const? Единственное приложение, о котором я мог думать, - это встроенное программирование, когда копия переменной может тратить драгоценное пространство.

Есть ли какие-нибудь простые примеры, возможно, где воздействие легко просматривается с помощью ссылки const?

Спасибо, erip

+0

Чтобы подтвердить свой вопрос, «зачем использовать' const int & a', а не 'int a' как аргумент?"? –

+0

В противном случае подпрограмма могла бы изменить переданный 'int' - и на самом деле следует ожидать этого. Посмотрите все на [const correctness] (http://www.parashift.com/c++-faq/const-correctness.html). – davidhigh

+0

@erip Забавно, потому что вы спрашиваете, какой смысл делать ссылку 'const'. Что подсказывает, что вы спрашиваете о 'int &' vs. 'const int &'. – juanchopanza

ответ

4

Рассмотрим следующие три примера:

(i) void setAge(int &a) { age = a; } 
(ii) void setAge(const int &a) { age = a; } 
(iii) void setAge(int a) { age = a; } 

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

Затем, используя случай (i), вызывающий абонент не может знать, что a не был изменен впоследствии.

int a=3; 
dog.setAge(a); //case (i): what is "a" afterwards? 

Никто не знает, какое значение имеет a после вызова функции - на самом деле, функция подписи сообщает абоненту, что изменение a, вероятно, произойдет.

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

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

Что касается целого const correct -topic, см. here.

3

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

std::vector может быть примером, объект Matrix - еще один пример.

3
void setAge(const int &a) { age = a; } 

Вы передаете const int reference, вы не намерены изменять значение a внутри функции setAge.

void setAge(int &a) { age = a; } 

Вы передаете int reference, вы не заботитесь ли функция setAge изменить значение a внутри функции ЗеЬАде.

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

Вы можете прочитать больше о сопзИ корректности здесь https://isocpp.org/wiki/faq/const-correctness#overview-const

5

Изготовления копии переменных отходов драгоценного места и отходов драгоценных времени, поэтому избежать ненужных копий является то, чтобы беспокоиться о том, в каком-либо программах, а не только встроенный. По этой причине ссылки для передачи параметров только для чтения всегда были идиомой в C++.

Однако он обычно предназначен для передачи в «тяжелых» объектах, то есть объектах, которые относительно дороги для копирования. Использование его со скалярными типами (как в вашем примере) практически не имеет смысла.

+0

Да, это имеет смысл. Я думал о том, что количество копий по нескольку раз было бы бесполезным. Передача ссылки на массив, 'std :: vector' или любой другой общий объект будет иметь больший смысл. – erip

Смежные вопросы