Лекции по программированию

Автор: Пользователь скрыл имя, 17 Января 2011 в 18:57, курс лекций

Описание работы

6 тем.

Работа содержит 1 файл

Лекции.doc

— 615.00 Кб (Скачать)

      *( a ++); //2 значение указателя изменяется на величину sizeof (int)

      cout <<a<<"\t" <<*a<<endl;

      * a ++; //3с учетом приоритета операций * и ++ аналог строки 2

      cout <<a<<"\t" <<*a<<endl;

      return 0;

    }

Результат работы программы:

Address * a
00355900 50
00355900 51
00355904 -31686019
00355908 393224

Замечание. В строке 2 значение указателя изменилось на величину sizeof (int) в нашем случае на 4 байта, в результате чего от адреса 00355900 мы перешли к адресу 00355904. Т.к. данные по новому адресу нами не были инициализированы, то на экран вывелось случайное число. Аналогичным образом была выполнена строка 3.

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

    6.2. Ссылки

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

    <базовый тип> & <имя ссылки>

Например:

    int a ; //целочисленная  переменная

    int & b = a ; //ссылка  на целочисленную переменную а

Рассмотрим следующий  пример:

    # include < iostream >

    using namespace std;

    int main()

    {

      int a =50; //целочисленная переменная а

      int & b = a ; //ссылка b – альтернативное имя для переменной а

      cout<<"a\t b\n";

      cout <<a <<"\t"<<b<<endl;

      a++; //1

      cout <<a <<"\t"<<b<<endl;

      b++; //2

      cout <<a <<"\t"<<b<<endl;

      return 0;

    }

Результат работы программы:

A b
50 50
51 51
52 52

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

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

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

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

3) Повторная инициализация  ссылки невозможна.

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

    6.3. Одномерные массивы

Одномерный массив – это фиксированное количество элементов одного и того же типа, объединенных общим именем, где каждый элемент имеет свой номер. Нумерация элементов массива в С++начинается с нулевого элемента, то есть, если массив состоит из 10 элементов,то его элементы будут иметь следующие номера: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.Элементы массива могут быть любого типа, в том числе и структурированного(кроме файлового).

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

Статические одномерные массивы

Формат объявления статического массива:

    <базовый тип> <имя массива>[<размер массива>]={<список  инициализации>}

Замечание. В данном случае [] являются операцией индексации, а не признаком необязательного элемента в формате объявления массива.

Одновременно с  объявлением массива может проводиться  его инициализация, например:

    float v [10]; // массив  из10 элементов с плавающей точкой, не инициализирован

    int a []={1,2,3}; // массив  из 3 элементов целого типа, инициализирован

    // списком чисел  1, 2, 3

    int b [5]={1,2,3}; //массив  из 5 элементов целого типа, инициализирован

    // списком чисел  1, 2, 3, 0, 0

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

Для обращения к  элементу массива указывается имя  массива, а затем в квадратных скобках индекс (номер). В примере, рассмотренном выше, для обращения к элементу массива а с номером 2нужно записать a [2], к элементу с номером ноль – a [0]. Индексом может быть любое целое выражение, образуемое целыми переменными и целыми константами.

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

    int b [10]; //объявление массива

    for ( int i = 0; i <10; i ++) //ввод элементов массива

      cout<<”b[”<<i<<”]=”;

      cin>>b[i];

    }

    for ( int i = 0; i <10; i ++) //вывод элементов массива на экран

      cout <<” b [”<< i <<”]=”<< b [ i ]<<”\ n ”;

Динамические  одномерные массивы

Динамические одномерные массивы отличаются от статических  тем, что:

1) имя массива является  указателем-переменной;

2) память под элементы массива выделяется в куче с помощью специальной команды new.

Формат объявления динамического массива: 

    <базовый тип> * <имя массива>= new <базовый тип> [<размерность массива>];

Замечание. В данном случае [] являются операцией индексации, а не признаком необязательного элемента в формате объявления массива.

Например:

    float * v =new float [10]; //вещественный массив из 10элементов, не инициализирован

    int * a = new int [3]; // массив из 3 элементов целого типа, не инициализирован

Обращаться к элементам массива можно через индексы, как и для статических массивов, а можно и через указатели. Например, чтобы обратиться к нулевому элементу массива можно написать a[0]или , а для обращения к элементу массива а с номером i нужно написать a [ i ] или *(а+ i ).

Рассмотрим более  подробно обращение к элементам  массива через указатели. Указатель хранит адрес нулевого элемента массива, поэтому, когда мы выполняем операцию , то мы обращаемся к значению, которое хранится по данному адресу. Выражение *(а+2),говорит о том, что вначале мы сдвинемся по отношению к нулевому элементу массива а на столько байт, сколько занимают 2 элемента, а затем обратимся к значению, которое там хранится.

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

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

    int * b = new int [10]; //объявили динамический массив, для хранения 10 целых чисел

    for (int i=0;i<10; i++) // ввод элементов массива

    {cout<<"b["<<i<<"]=";

    cin >>*( b + i );} //введенное значение записываем в i-тый элемент массива b

    for ( int i =0; i <10; i ++) // вывод элементов массива

cout <<" b ["<< i <<"]="<<*( b + i )<< endl ;//выводи на экран значение i-того элемента массива b

Освободить память, выделенную под динамический массив можно с помощью операции delete. Например, освобождение памяти, выделенной под элементы массива b из предыдущего примера, производится следующим образом:

    delete [] b ;

Замечание. Если в данной записи пропустить квадратные скобки, то ошибки не будет, однако освобождена будет память, выделенная под нулевой элемент массива, а с остальными элементами массива «связь» будет потеряна и они не будут доступны для дальнейших операций.Такие ячейки памяти называются мусоромКроме того, операция delete освобождает память, выделенную в куче под элементы массива, а сам указатель при этом сохраняется и может повторно использоваться для определения другого массива. 

Передача  одномерных массивов в качестве параметров 

При использовании  в качестве параметра одномерного массива в функцию передается указатель на его нулевой элемент. Напомним, что указателем на нулевой элемент является имя одномерного массива. Операцию разадресации внутри функции при обращении к элементам массива выполнять не надо, т.к. запись вида a[i] автоматически заменяется компилятором на выражение *(a+i).

При передаче массива  в качестве параметра функции  информация о количестве элементов  теряется, поэтому размерность массива  следует передавать в качестве отдельного параметра. Рассмотрим несколько примеров.

1. Передача статического  массива:

    #include <iostream>

    using namespace std;

    /*в  функцию в качестве  параметров передаются  статический массив mas и его размерность n */

    void print (int mas[], int n)

    {

      for (int i=0; i<n; i++) cout<<mas[i]<<"\t";

      cout<<endl; 

    } 

    int main()

    {

      int a[10]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

      print(a,10); 

      cout<<endl;

      print (a, 7);

      print(a, 13);

      return 0;

    }

Результат работы программы:

0 1 2 3 4 5 6 7 8 9

0 1 2 3 4 5 6

0 1 2 3 4 5 6 7 8 9 -858993406 1245112 4269558 

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

2. Передача динамического  массива

    #include <iostream>

    using namespace std;

    /*в  функцию в качестве  параметров передаются  динамический массив mas и его размерность n */

    void print (int *mas, int n)

      for (int i=0; i<n; i++) 

      cout<<mas[i]<<"\t";

    }

    int main()

Информация о работе Лекции по программированию