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.
Читать Си-строки можно разными способами, например
# include
fgets(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;
}