КАТЕГОРИИ: Архитектура-(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) |
Инициализация указателей
Указатели чаще всего используются при работе с динамической памятью, называемой некоторыми эстетами кучей (перевод с английского языка слова heap). Это свободная память, в которой можно во время выполнения программы выделять место в соответствии с потребностями. Доступ к выделенным участкам динамической памяти, называемым динамическими переменными, производится только через указатели. Время жизни динамических переменных – от точки создания до конца программы или до явного освобождения памяти. В С++ используется два способа работы с динамической памятью. Первый использует семейство функций malloc и достался в наследство от С, второй использует операции new и delete. При определении указателя надо стремится выполнить его инициализацию, то есть присвоение начального значения. Непреднамеренное использование неинициализированных указателей – распространённый источник ошибок в программах. Инициализатор записывается после имени указателя либо в круглых скобках, либо после знака равенства. Существуют следующие способы инициализации указателя: 1. Присваивание указателю адреса существующего объекта: · с помощью операции получения адреса: int a=5; //целая переменная int * p=&a; //в указатель записывается адрес а int * p (&a); //то же самое другим способом · с помощью значения другого инициализированного указателя: int * r=p; · с помощью именами массива или функции, которые трактуются как адрес: int b[10]; //массив int * t=b; //присваивание адреса начала массива … void f(int5 a){/*…*/} //определение функции void (*pf)(int); //указатель на функцию pf=f; //присваивание адреса функции 2. Присваивание указателю адреса области памяти в явном виде: Char * vp=(char )0 хВ8000000; Здесь 0хВ000000 – шестнадцатеричная константа, (char *) – операция приведения типа: константа преобразуется к типу «указатель на char». 3. Присваивание пустого значения: int * suxx=NULL; int * rulez=0; В первой строке используется константа NULL, определённая в некоторых заголовочных файлах С как указатель, равный нулю. Рекомендуется использовать просто 0, так как это значение типа int будет правильно преобразовано стандартными способами в соответствии с контекстом. Поскольку гарантируется, что объектов с нулевым адресом нет, пустой указатель можно использовать для проверки, ссылается указатель на конкретный объект или нет. 4. Выделение участка динамической памяти и присваивание её адреса указателю: · с помощью операции new: int * n=new int; //1 int * m=new int (10); //2 int * q=new int [10]; //3 · c помощью функции malloc: int * u=(int *)malloc(sizeof(int)); //4 В операторе 1 операция new выполняет выделение достаточного для размещения величины типа int участка динамической памяти и записывает адрес начала этого участка в переменную n. Память под саму переменную n (размера, достаточного для размещения указателя) выделяется на этапе компиляции. В операторе 2, кроме описанных выше действий, производится инициализация выделенной динамической памяти значением 10. В операторе 3 операция new выполняет выделение памяти под 10 величин типа int (массива из 10 элементов) и записывает адрес начала этого участка в переменную q, которая может трактоваться как имя массива. Через имя можно обращаться к любому элементу массива. Если память выделить не удалось, по стандарту должно порождаться исключение bad_alloc. Старые версии компиляторов могут возвращать 0. В операторе 4 делается то же самое, что и в операторе 1, но с помощью функции выделения памяти malloc, унаследованной из библиотеки С. В функцию передаётся один параметр – количество выделяемой памяти в байтах. Конструкция (int) используется для приведения типа указателя, возвращаемого функцией, к требуемому типу. Если память выделить не удалось, функция возвращает 0. Операцию new использовать предпочтительнее, чем функцию malloc, особенно при работе с объектами. Освобождение памяти, выделенной с помощью операции new, должно выполняться с помощью delete, а памяти, выделенной функцией malloc – посредством функции free. При этом переменная-указатель сохраняется и может инициализироваться повторно. Приведённые выше динамические переменные уничтожаются следующим образом: delete n; delete m; delete [] q; free (u); Если память выделялась с помощью new [], для освобождения памяти необходимо применять delete []. Размерность массива при этом не указывается. Если квадратных скобок нет, то никакого сообщения об ошибке не выдаётся, но помечен как свободный будет только первый элемент массива, а остальные окажутся недоступны для дальнейших операций. Такие ячейки памяти называются мусором. Внимание! Если переменная-указатель выходит за области своего действия, отведённая под неё память освобождается. Следовательно, динамическая переменная, на которую ссылался указатель, становится недоступной. При этом память из-под самой динамической переменной не освобождается. Другой случай появления «мусора» - когда инициализированному указателю присваивается значение другого указателя. При этом старое значение бесследно теряется.
С помощью комбинаций звёздочек, круглых и квадратных скобок можно описывать составные типы и указатели на составные типы, например, в операторе int *(*p[10])(); объявляется массив из 10 указателей на функции без параметров, возвращающих указатели на int. По умолчанию квадратные и круглые скобки имеют одинаковый приоритет, больший, чем звёздочка, и рассматриваются слева на право. Для изменения порядка рассмотрения используются круглые скобки. При интерпретации сложных описаний необходимо придерживаться правила «изнутри наружу»: 1. если справа от имени имеются квадратные скобки, это массив, если скобки круглые – это функция; 2. если слева есть звёздочка, это указатель на проинтерпретированную ранее конструкцию; 3. если справа встречается закрывающая скобка, необходимо применить приведённые выше правила внутри скобок, а затем переходить наружу; 4. в последнюю очередь интерпретируется спецификатор типа. Для приведённого выше описания порядок интерпретации указан цифрами: int *(*p[10]) (); 5 4 2 1 3 //порядок интерпретации описания
Раздел 5. Строки.
Дата добавления: 2014-01-11; Просмотров: 410; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |