21 июня 2015 г.

обновлённый пример с операторами new и delete

#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
void main(){
srand(time(NULL));
int size;
int * dar;
// запрос размера массива с клавиатуры
cout << "Enter size:\n";
cin >> size;
//выделение памяти под массив с количеством элементов size
dar = new int[size];
if (!dar){
cout << "Sorry, error!!!";
exit(0);// функция организует выход из программы
}
// заполнение массива и показ на экран
for (int i = 0; i<size; i++){
dar[i] = rand() % 100;
cout << dar[i] << "\t";
}
cout << "\n\n";
// освобождение памяти
delete[]dar;
}

Операция освобождения памяти delete

Операция delete освобождает для дальнейшего использования в программе участок памяти, ранее выделенной операцией new:

delete ip; // Удаляет динамический объект типа int,
// если было ip = new int;
delete [ ] mas; // удаляет динамический массив длиной 50, если было
// double *mas = new double[50];

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

Чтобы избежать подобных ошибок, можно применять следующую конструкцию:

int *ip=new int[500];
. . .
if (ip){
delete ip; ip=NULL;
}
else
{
cout <<" память уже освобождена \n";
}

Операция выделения памяти new

При выделении памяти объект можно инициализировать:
int *ip = new int(3);

Можно динамически распределить память и под массив:
double *mas = new double [50];

Далее с этой динамически выделенной памятью можно работать как с обычным массивом:


#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
void main(){
srand(time(NULL));
int size;
int * dar;
// запрос размера массива с клавиатуры
cout << "Enter size:\n";
cin >> size;
//выделение памяти под массив с количеством элементов size
dar = new int[size];
if (!dar){
cout << "Sorry, error!!!";
exit(0);// функция организует выход из программы
}
// заполнение массива и показ на экран
for (int i = 0; i<size; i++){
dar[i] = rand() % 100;
cout << dar[i] << "\t";
}
cout << "\n\n";
}

Нахождение максимального элемента в массиве и замена его на нуль

#include <iostream>
using namespace std;
Функция определяет ссылку на элемент
массива с максимальным значением.
int &rmax(int n, int d[])
{
int im = 0;
for (int i = 1; i<n; i++)
im = d[im]>d[i] ? im : i;
return d[im];
}

void main()
{
int x[] = { 10, 20, 30, 14 };
int n = 4;
cout << "\nrmax(n,x) = " << rmax(n, x) << "\n";
rmax(n, x) = 0;
for (int i = 0; i<n; i++)
cout << "x[" << i << "]=" << x[i] << " ";
cout << "\n";
}

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

#include <iostream>
using namespace std;
int a[10][2];
void main()
{
int & rf(int index); //Прототип функции.
int b;
cout << "Fill array.\n";
for (int i = 0; i<10; i++)
{
cout << i + 1 << " element: ";
cin >> b;
a[i][0] = b;
rf(i) = b;
}
cout << "Show array.\n";
cout << "1-st column 2-nd column" << "\n";
for (int i = 0; i<10; i++)
cout << a[i][0] << "\t\t" << rf(i) << "\n";
}

int &rf(int index)
{
return a[index][1]; //Возврат ссылки на элемент массива.
}

Здесь объявляется глобальный двумерный массив a, состоящий из целых чисел.
В начале функции main() содержится прототип ссылочной функции rf(),
которая возвращает ссылку на целое значение второго столбца массива a,
которое однозначно идентифицируется параметром-индексом index.
Так как функция rf() возвращает ссылку на целое значение, то имя функции
может оказаться слева от оператора присваивания, что продемонстрировано в строке: rf(i) = b;

Ссылочные параметры. Передача аргументов по ссылке.

#include <iostream>
using namespace std;
//Обмен с использованием указателей.
void interchange_ptr(int *u, int *v)
{
int temp = *u;
*u = *v; *v = temp;
}
//Обмен с использованием ссылок.
void interchange_ref(int &u, int &v)
{
int temp = u;
u = v; v = temp;
}
void main()
{
int x = 5, y = 10;
cout << "Change whis pointers:\n";
cout << "x = " << x << " y = " << y << "\n";
interchange_ptr(&x, &y);
cout << "x = " << x << " y = " << y << "\n";
cout << "-----------------------------------------" << "\n";
cout << "Change whis references:\n";
cout << "x = " << x << " y = " << y << "\n";
interchange_ref(x, y);
cout << "x = " << x << " y = " << y << "\n";
}

Инициализация ссылок

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

#include <iostream>
using namespace std;
void main()
{
int ivar = 1234; //Переменной присвоено значение.
int *iptr = &ivar; //Указателю присвоен адрес ivar.
int &iref = ivar; //Ссылка ассоциирована с ivar.
int *p = &iref; //Указателю присвоен адрес iref.

cout << "ivar = " << ivar << "\n";
cout << "*iptr = " << *iptr << "\n";
cout << "iref = " << iref << "\n";
cout << "*p = " << *p << "\n";
}


Замечания.

1. В отличие от указателей, которые могут быть объявлены неинициализированными или установлены в нуль(NULL), ссылки всегда ссылаются на объект.Для ссылок ОБЯЗАТЕЛЬНА инициализация при создании и не существует аналога нулевого указателя.
2. Ссылки нельзя инициализировать в следующих случаях :
при использовании в качестве параметров функции.
при использовании в качестве типа возвращаемого значения функции.
в объявлениях классов.
3. Не существует операторов, непосредственно производящих действия над ссылками!