void swap(int х, int у) /* НЕВЕРНО */
{
int temp;
temp = х;
x = y;
у = temp;
}При вызове с параметрами a, b внутри функции создаются новые переменные x и y, они получают значения a и b, далее они обмениваются этими значениями и…уничтожаются при выходе из функции. Значения собственно a и b остаются без изменений!
int a; //переменная типа int
int *pa; //переменная типа «указатель на int»Создавать неинициализированные переменные плохо. Неинициализированные указатели – вдвойне. Лучше, создавая переменную указатель поместить в нее какой-нибудь конкретный адрес. Адрес переменной можно получить при помощи «операции получения адреса», для этого используют амперсанд:
int *pa = &a; //указатель pa будет указывать на a
*pa = 5 //положить 5 в переменную, на которую указывает pa
*pa++ //увеличить на единицу переменную, на которую указывает paТеперь можно правильно написать функцию swap:
void swap(int *х, int *у)
{
int temp;
temp = *х;
*x = *y;
*у = temp;
}Работа производится с указателями, вернее с ячейками, на которые они указывают. Использовать функцию следует так
swap(&a, &b)В функции. Передаются не значения a и b, а их адреса. Благодаря операции разыменования именно a и b меняются своими значениями!
Это же происходит в функции scanf.
int a = 0; int b = 0; scanf("%d%d", &a, &b);Ей надо передать именно адрес переменной, а не ее значение, чтобы она смогла заложить результат в правильный адрес памяти (в нашу переменную). Именно этим объясняется наличие амперсанда перед переменными при вызове scanf.
*a = 5;положит 5 в нулевую ячейку массива a.
int *p = a;
for (int i = 0; i < 10; i++)
{
printf(“%d ”, *p);
p++;
}Указатели можно вычитать друг из друга. Получим «расстояние» между ячейками, на которые они указывают. Других операции, например, деление, умножение на число, сложение указателей в языке не предусмотрено.
char *s = "abc"Строка состоит из четырех ячеек. Последний символ с кодом 0. Читать Си-строки можно разными способами, например
# includefgets(s, 100, stdin); // будет прочитано максимально 100 символов
#includeДля строк все то же самоеint main() { std::cout << "Enter a positive integer: "; int length; std::cin >> length; int *array = new int[length]; // используем оператор new[] для выделения массива. Обратите внимание, переменная length не обязательно должна быть константой! std::cout << "I just allocated an array of integers of length " << length << '\n'; array[0] = 7; // присваиваем элементу под индексом 0 значение 7 delete[] array; // используем оператор delete[] для освобождения выделенной массиву памяти array = NULL; // используйте nullptr вместо 0 в C++11 return 0; }
char *s = new char[1000]; detete[] s;
char *s = NULL; while(true) { s = new char[1000]; }
Рано или поздно программа переполнит память. Такая ситуация называется утечкой памяти.
В ООП при удалении объекта вызывается деструктор, функция, имя которой совпадает с именем класса, с тильдой в начале. В деструкторе нужно обязательно нужно освобождать память при помощи delete[].
Например:
struct MyClass { char *t; MyClass(); ~MyClass(); }; MyClass::MyClass() { std::cout << "Constructor called" << endl; // выделяем память t = new char[4]; t[0] = 'a'; t[1] = 'b'; t[2] = 'c'; t[3] = '\0'; } MyClass::~MyClass() { std::cout << "Destructor called" << endl; // освобождаем память delete[] t; }