Студопедия

КАТЕГОРИИ:


Архитектура-(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)

Правила работы со ссылками

...

Нулевой указатель

Void

Бестиповый указатель

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

void* ptr;

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

В программе на языке Си++ бестиповый указатель может применяться там, где адрес интерпретируется по-разному, в зависимости от каких-либо динамически вычисляемых условий. Например, приведенная ниже функция будет печатать целое число, содержащееся в одном, двух или четырех байтах, расположенных по передаваемому адресу:

printbytes(void* ptr, int nbytes)

{

if (nbytes == 1) {

char* cptr = (char*)ptr;

cout << *cptr;

} else if (nbytes == 2) {

short* sptr = (short*)ptr;

cout << *sptr;

} else if (nbytes == 4) {

long* lptr = (long*)ptr;

cout << *lptr;

} else {

cout << "Неверное значение аргумента";

}

}

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

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

long* foo(void);

long* resPtr;

if ((resPtr = foo())!= 0) {

// использовать результат

} else {

// ошибка

}

В языке Си++ определена символическая константа NULL для обозначения нулевого значения указателя.

Такое использование нулевого указателя было основано на том, что по адресу 0 данные программы располагаться не могут, он зарезервирован операционной системой для своих нужд. Однако во многом нулевой указатель – просто удобное соглашение, которого все придерживаются.

Ссылки

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

int i = 1;

int& r = i; // r и i ссылаются на одно и то же целое

int x = r; // x = 1

r = 2; // i = 2;

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

int ii = 0;

int& rr = ii;

rr++; // ii увеличивается на 1

Здесь операция ++ допустима, но rr++ не увеличивает саму ссылку rr; вместо этого ++ применяется к целому, т.е. к переменной ii. Следовательно, после инициализации значение ссылки не может быть изменено: она всегда указывает на тот объект, к которому была привязана при ее инициализации. Чтобы получить указатель на объект, обозначаемый ссылкой rr, можно написать &rr. Очевидной реализацией ссылки может служить постоянный указатель, который используется только для косвенного обращения. Тогда инициализация ссылки будет тривиальной, если в качестве инициализатора указан адрес (т.е. объект, адрес которого можно получить). Инициализатор для типа T должен быть адресом. Однако, инициализатор для &T может быть и не адресом, и даже не типом T. В таких случаях делается следующее:

1. во-первых, если необходимо, применяется преобразование типа;

2. затем получившееся значение помещается во временную переменную;

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

Пусть имеются описания:

double& dr = 1; // ошибка: нужен адрес

const double& cdr = 1; // нормально

Это интерпретируется так:

double* cdrp; // ссылка, представленная как указатель

double temp;

temp = double(1);

cdrp = &temp;

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

Переменная-ссылка должна явно инициализироваться при ее описании, кроме случаев, когда она является параметром функции, описана как extern или ссылается на поле данных класса.

После инициализации ссылке не может быть присвоена другая переменная.

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

Не разрешается определять указатели на ссылки, создавать массивы ссылок и ссылки на ссылки.

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

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

<== предыдущая лекция | следующая лекция ==>
Операции с указателями | Динамические объекты в С
Поделиться с друзьями:


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


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



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




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