Когда происходит вызов функции find_char()
, ей передаются три аргумента: строка, в которой осуществляется поиск, искомый символ и объект типа size_type
(раздел 3.2.2), содержащий счетчик вхождений. Если s
является объектом класса string
, a ctr
— объектом типа size_type
, то функцию find_char()
можно вызвать следующим образом:
auto index = find_char(s, 'o', ctr);
После вызова значением объекта ctr
будет количество вхождений символа о
, a index
укажет на его первое вхождение, если оно будет. В противном случае значение index
будет равно s.size()
, a ctr
— нулю.
Упражнение 6.11. Напишите и проверьте собственную версию функции reset()
, получающую ссылку.
Упражнение 6.12. Перепишите программу из упражнения 6.10 раздела 6.2.1 так, чтобы использовать ссылки вместо указателей при смене значений двух целочисленных переменных. Какая из версий, по вашему, проще в использовании и почему?
Упражнение 6.13. Если Т
— имя типа, объясните различие между функцией, объявленной как void f(Т)
и как void f(Т&)
.
Упражнение 6.14. Приведите пример, когда параметр должен быть ссылочным типом. Приведите пример случая, когда параметр не должен быть ссылкой.
Упражнение 6.15. Объясните смысл каждого из типов параметров функции find_char()
. В частности, почему s
— ссылка на константу, a occurs
— простая ссылка? Почему эти параметры ссылочные, а параметр с типа char
нет? Что будет, сделай мы s
простой ссылкой? Что если occurs сделать константной ссылкой?
6.2.3. Константные параметры и аргументы
При использовании параметров, являющихся константой, следует помнить об обсуждении спецификатора const
верхнего уровня из раздела 2.4.3. Как упоминалось в этом разделе, спецификатор const
верхнего уровня — это тот спецификатор, который относится непосредственно к объекту:
const int ci = 42; //
int i = ci; //
//
int * const p = &i // const верхнего уровня; нельзя присвоить p
*p = 0; //
Как и при любой другой инициализации, при копировании аргумента для инициализации параметра спецификаторы const
верхнего уровня игнорируются. В результате спецификатор const
верхнего уровня для параметров игнорируется. Параметру, у которого есть спецификатор const
верхнего уровня, можно передать и константный, и неконстантный объект:
void fcn(const int i) { /* fcn
Функцию fcn()
можно вызвать, передав ей аргумент типа const int
или обычного типа int
. Тот факт, что спецификаторы const
верхнего уровня игнорируются у параметра, может иметь удивительные последствия:
void fcn(const int i) { /*
void fcn(int i) { /* ... */ } //
В языке С++ можно определить несколько разных функций с одинаковым именем. Однако это возможно только при достаточно большом различии их списков параметров. Поскольку спецификаторы const
верхнего уровня игнорируются, мы можем передать те же типы любой версии функции fcn()
. Вторая версия функции fcn()
является ошибкой. Несмотря на внешний вид, ее список параметров не отличается от списка первой версии функции fcn()
.
Поскольку параметры инициализируются так же, как и переменные, имеет смысл напомнить общие правила инициализации. Можно инициализировать объект со спецификатором const
нижнего уровня неконстантным объектом, но не наоборот, а простую ссылку следует инициализировать объектом того же типа.
int i = 42;
const int *cp = &i //
const int &r = i; //
const int &r2 = 42; //
int *p = cp; //
int &r3 = r; //