Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Константы. Переменная, объявленная как ссылка, служит псевдонимом другой переменной




Ссылки и функции

Ссылки

Переменная, объявленная как ссылка, служит псевдонимом другой переменной. Ссылку объявляют, используя оператор ссылки &.

int Count = 0;

int &RefCount * Count;

В этом примере переменная Re f Count объявлена как ссылка на данные типа int и инициализирована так, что ссылается на переменную Count типа int. Это определение заставляет RefCount стать псевдонимом переменной Count, т. е. и Re f Count, и Count будут ссылаться на одно и то же место в памяти. Две переменные всегда имеют одинаковые значения, а присваивание, сделанное для одной переменной, изменяет значение другой. Например:

int Count =» 0;

int &RefCount = Count; // здесь и Count, и RefCount равны О

Ref Count = 1; // здесь и Count, и RefCount равны 1

++Count; // здесь и Count, и RefCount равны 2

Примечание

Пробел непосредственно перед или после оператора & несущественен. Следовательно, можно объявить RefCount как int & RefCount, int & RefCount, int & RefCount или даже int & RefCount (хотя последняя форма трудно читаема).

Если переменная определяется как ссылка, она должна быть инициализирована переменной объявленного типа. Как только эта инициализация выполнена, ссылаться на другие переменные уже нельзя. Кроме того, нельзя инициализировать ссылочную переменную значениями констант (например, 5 или 'а'), если переменная не объявлена как ссылка на тип const (описан далее в разделе «Константы»).

int &RInt = 5; // ОШИБКА

Примечание

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

Ссылочная переменная существенно отличается от указателя. Указатель ссылается на область памяти, содержащую адрес целевой ячейки, а ссылочная переменная – непосредственно на целевую ячейку памяти (в точности совпадая с переменной, используемой для ее инициализации). На рис. 2.1 показаны различия между переменной, ссылкой и указателем на нее. Допустим, что были заданы следующие объявления:

int Count = 0;

int &RefCount = Count;

int *PtrCount = &Count;

Обратите внимание: указатель PtrCount в приведенном коде может быть объявлен и инициализирован.

int *PtrCount = &RefCount; // что эквивалентно:

// int *PtrCount = &Count;

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

Параметры функции и тип возвращаемого функцией значения можно объявить с помощью ссылок. Например, следующая функция имеет параметр, который ссылается на переменную типа int:

void FuncA (int &Parm);

При вызове этой функции ей передается переменная типа int, которая используется для инициализации ссылки на параметр Parm. Внутри кода функции параметр Parm является псевдонимом переменной, переданной при вызове, и любые изменения Parm также влияют и на саму переменную. Таким образом, ссылочный параметр предоставляет способ передачи параметра в функцию по ссылке, а не по значению (а в языках С и C++ нессылочные параметры передаются значением, т.е. функция получает копию оригинала переменной). Следующий код показывает различие между ссылочным и нессылочным параметром.

Рис. 2.1. Переменная, ссылка и указатель на нее

void FuncA (int &Parm) //ссылочный параметр

{

++Parm;

}

void FuncB (int Farm) //нессылочный параметр

{

++Parm;

}

void main()

{

int N = 0;

FuncA (N); // N передается по ссылке

// здесь N равно 1

FuncB (N); // передается через значение

// здесь N все еще равно 1

}

В этом примере функции FuncA и FuncB увеличивают значение параметра Parm. Однако только функция FuncA, которая получает параметр как ссылку, изменяет значение переменной N, передаваемой из вызывающей функции. Нельзя передать константу (например, 5) как параметр, если последний не объявлен как ссылка на тип const (см, раздел «Константы и функции»).

void FuncA (int &RInt); void main ()

{

FuncA (5); // СШИБКА: ссылка не может инициализироваться значением константы

//...

}

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

Чтобы использовать преимущества, предоставляемые ссылочным параметром, в языке C++, как и в языке С, можно использовать в качестве параметра указатель. (В частности, возможность изменения переменной, передаваемой вызывающей программой, и устранение операции копирования.) Однако ссылочными параметрами можно манипулировать с помощью более простого синтаксиса, подобного применяемому при работе с обычными переменными.

Оператором &, можно объявить функцию, возвращающую ссылку. Например:

int & Get Index();

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

int N;

 

N = Getlndex(); // копирует значение переменной типа int

Getlndex() = 5; //-присваивает 5 переменной типа int

++Getlndex(); // увеличивает значение переменной типа int

Следующий код показывает, как можно реализовать функцию GetIndex, и иллюстрирует эффект вызова функции.

int Index = 0; int &Getlndex()

{

return Index;

}

 

void main ()

{

int N; // здесь Index равно 0

N - GetIndex {);

// здесь Index равно 0 и N равно О

GetIndex () - 5;

// здесь Index равно 5

++GetIndex ();

// здесь Index равно б

}

Функция, возвращаемое значение которой является ссылкой, должна возвращать переменную соответствующего типа и может возвращать константу, – например 5, только в случае, если она объявлена как возвращающая ссылку на тип const (см. «Константы и функции»). Возвращаемая переменная используется для инициализации временной ссылочной переменной, создаваемой при вызове функции. Другими словами, полагая, что Index и GetIndex определены так, как показано выше, оператор

++GetIndex (); // вызов функции приводит к созданию временной

// ссылочной переменной, являющейся псевдонимом переменной Index

эквивалентен коду

int &Temp = Index; // объявление и инициализация действительной

// ссылки на переменную

++Теmр;

В этих примерах значение переменной index увеличивается на 1.

Поскольку ссылка, создаваемая при вызове функции, используется после возврата из функции, последняя не может возвратить ссылку на переменную, которая уничтожается после выхода из функции. Например, нельзя возвратить ссылку на автоматическую переменную или параметр, как показано в следующем «опасном» коде.

int &BadIdeal()

{

int i;

return i;

}

 

int &BadIdea2 {int Farm)

{

return Parm;

}

Этот код не вызывает ошибок компилятора, однако результат использования ссылки одной из этих функций непредсказуем. Функция, возвращающая ссылку, может "безопасно" вернуть только глобальную переменную, переменную типа static или переменную, память для которой выделяется динамически (см. параграф «Операторы new и delete»).

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

Примечание

В следующих главах приведены примеры передачи и возврата ссылок из функций.

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

const int MaxLines = 100;

Примечание

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

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

const double CD = 2.5;

double D;

 

D = CD; // для чтения константы

 

CD = 5.0; // СШИБКА: нельзя присвоить новое значение константе

 

++CD; // ОШИБКА: нельзя изменить значение типа const

Константную переменную можно инициализировать, используя как константное выражение (например, 5), так и другую переменную. Например, все приведенные ниже определения константных переменных являются корректными (первые два инициализируют константу с константными выражениями, а вторые два – с другими переменными).

void Func (int Farm)

{

int I = 3;

const int CI1 = 5;

const int CI2 = 2 * sizeof(float);

const int CI3 = I;

const int CI4 = Parm;

}

Если константная переменная инициализирована выражением, содержащим другие переменные, то ее нельзя использовать для определения размерности массива. (Этот метод может оказаться некорректным для динамически создаваемого массива, размер которого определяется во время выполнения. В последнем параграфе главы проанализированы корректные методы выделения памяти динамическим массивам.) Например:

void Func (int Farm)

{

const int CI1 = 100;

const int CI2 = Parm;

char Bufl [CIl]; // правильно

char Buf2 [CI2]; // ОШИБКА: требуется константное выражение

}

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

Примечание

Константная переменная имеет преимущества перед константой, определенной оператором #define, так как к ней можно обратиться с помощью символического отладчика.




Поделиться с друзьями:


Дата добавления: 2014-01-07; Просмотров: 603; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.058 сек.