
- •3.Динамическая память. Указатели и массивы. Ссылочный тип.
- •5.Доступ к элементам массива. Вычисление размера массива. Многомерные массивы.
- •7.Использование new и delete на примере динамических
- •9.Символьные массивы и строковые функции. Массивы в
- •13.Условный оператор? . Оператор switch.
- •15.Классы (fstream, ofstream, ifstream, ostream, istream, ios) и представители классов потокового ввода-вывода.
- •19.Объявление переменных указателей. Простые операторы с указателями.
- •21.Оператор if. Оператор if-else. Вложенные операторы if-else. Оператор if-else-if.
- •23.Операции динамического распределения памяти.
- •25.Передача значений параметров по умолчанию. Передача параметров по ссылке и ссылочные переменные.
- •27.Приоритет переменных с файловой и локальной областями действия. Операция уточнения области действия.
- •29.Пространство имен. Операторы namespace и using.
1. Арифметические операции с указателями и с указателями на массивы.
С указателями можно выполнять следующие операции: разадресация (*), присваивание, сложение с константой, вычитание, инкремент (++), декремент (– –), сравнение, приведение типов. При работе с указателями часто используется операция получения адреса (&). Операция разадресации, или разыменования, предназначена для доступа к величине, адрес которой хранится в указателе. Эту операцию можно использовать как для получения, так и для изменения значения величины (если она не объявлена как константа):
char a;//переменная типа char
char * p = new char;/*выделение памяти под указатель и под динамическую переменную типа char */
*p = 'Ю'; a = *p;//присваивание значения обеим переменным
На одну и ту же область памяти может ссылаться несколько указателей различного типа. Примененная к ним операция разадресации даст разные результаты.
Арифметические операции с указателями (сложение, вычитание, инкремент и декремент) автоматически учитывают размер типа величин, адресуемых указателями. Эти операции применимы только к указателям одного типа и имеют смысл в основном при работе со структурами данных, последовательно размещенными в памяти, например, с массивами.
Указатели и массивы в языке С++ тесно связаны. Имя массива можно использовать как указатель на его первый элемент:
int main() { char alpha[] = "abcdefghijkl"; char* p = alpha; char ch; while (ch = *p++) cout << ch << " = " << int (ch) << " = 0" << oct(ch) << '\n'; }
Результат применения к указателям арифметических операций +, -, ++ или -- зависит от типа указуемых объектов. Если такая операция применяется к указателю p типа T*, то считается, что p указывает на массив объектов типа T. Тогда p+1 обозначает следующий элемент этого массива, а p-1 - предыдущий элемент. Отсюда следует, что значение (адрес) p+1 будет на sizeof(T) байтов больше, чем значение p.
Вычитание указателей определено только в том случае, когда они оба указывают на один и тот же массив. Результат вычитания одного указателя из другого равен числу (целое) элементов массива, находящихся между этими указателями. Можно складывать с указателем или вычитать из него значение целого типа; в обоих случаях результатом будет указатель. Если получится значение, не являющееся указателем на элемент того же массива, на который был настроен исходный указатель (или указателем на следующий за массивом элемент), то результат использования такого значения неопределен.
3.Динамическая память. Указатели и массивы. Ссылочный тип.
Программа может хранить информацию в основной памяти компьютера двумя основными способами. Первый из них использует глобальные и локальные переменные, включая массивы, структуры и классы. В случае глобальных и статических локальных переменных место хранения информации фиксируется на все время выполнения программы. В случае локальных переменных память выделяется в стеке. Вторым способом хранения информации служит использование системы динамического выделения памяти С++. В этом методе память для хранения информации выделяется из свободной области памяти по мере надобности и возвращается назад, т.е. освобождается, когда надобность в ней исчезла. Область свободной памяти лежит между областью памяти, где размещается программа, и стеком. Эта область называется кучей (heap) и используется для запросов на динамическое выделение памяти.
Преимуществом использования динамической памяти служит то, что одна и та же память может быть использована для хранения различной информации в процессе исполнения программы. Поскольку память выделяется для определенной цели и освобождается, когда ее использование завершилось, то можно использовать ту же самую память в другой момент времени для других целей в другой части программы. Другим преимуществом динамического выделения памяти является возможность создания с ее помощью связанных списков, двоичных деревьев и других динамических структур данных.
Ядром динамического выделения памяти языка С являются функции malloc() и free(), являющиеся частями стандартной библиотеки. Всякий раз, когда функцией malloc() осуществляется запрос на выделение памяти, выделяется порция имеющейся в наличии свободной памяти. Всякий раз, когда эта память освобождается с помощью функции free(), эта память возвращается назад системе.
Язык С++ определяет два оператора динамического выделения памяти — new и delete.
Указатели и массивы
Массивы и указатели тесно связаны между собой. Рассмотрим следующий фрагмент: char str [80], *p1; p1 = str; Здесь p1 устанавливается на первый элемент массива str. Если необходимо получить доступ к пятому элементу str, то следует написать str[4] или * (p1 +4) Оба оператора возвращают пятый элемент. Следует помнить, что индексация массивов начинается с нуля, поэтому для индексации str используется 4. К указателю p1 добавляется 4 для получения пятого элемента, поскольку p1 указывает на первый элемент str. (Надо помнить, что имя массива без индекса возвращает начальный адрес массива, то есть адрес первого элемента.)
С предоставляет два метода доступа к элементам массива. Это важно, поскольку арифметические действия с указателями могут выполняться быстрее, чем индексация массива. Поскольку скорость работы программы часто играет важную роль, использование указателей для доступа к элементам довольно типично в С.
Рассмотрим две упрощенные версии стандартной библиотечной функции puts() для демонстрации данных методов. Один вариант использует индексацию массива, а другой - указатели. Функция puts() выводит строку на стандартное устройство вывода: /* Использование массива */ int puts (const char *s) { register int t; for(t=0; s [t]; ++t) putchar (s [t]); return 1; } /* использование указателя */ int puts (const char *s) { while (*s) putchar (*s++); return 1; }
Ссылки как и указатели хранят адрес объекта, но с автоматическим доступом к самому объекту, т.е. по сути они являются синонимами переменных на которые ссылаются. При определении ссылочной переменной инициализирующее выражение обязательно. Из следующего примера видно, что ссылки чуточку удобнее указателей.
#include <iostream.h>
void swap_ref(int &a, int &b) { int c=a; a=b; b=c; }
void swap_ptr(int *a, int *b){ int c=*a; *a=*b; *b=c; }
int main(){int A=10,B=20;
cout << "A="<<A<<" B="<<B<<endl;
swap_ref(A,B);
cout << "after swap_ref(A,B): A="<<A<<" B="<<B<<endl;
swap_ptr(&A,&B);
cout << "after swap_ptr(&A,&B): A="<<A<<" B="<<B<<endl;
return 0;}